From f1cfe390b4f8744c9c5a41aa34a3458cec040b2d Mon Sep 17 00:00:00 2001 From: zgrguric Date: Fri, 29 Dec 2023 10:33:44 +0100 Subject: [PATCH] Handle multiple hook instances with same hash --- README.md | 13 ++- src/TxHookParser.php | 74 +++++++++----- tests/Tx01Test.php | 12 ++- tests/Tx03Test.php | 1 - tests/Tx09Test.php | 3 +- tests/Tx14Test.php | 93 +++++++++++++++++ tests/Tx15Test.php | 95 ++++++++++++++++++ tests/fixtures/tx14.json | 139 ++++++++++++++++++++++++++ tests/fixtures/tx15.json | 209 +++++++++++++++++++++++++++++++++++++++ 9 files changed, 609 insertions(+), 30 deletions(-) create mode 100644 tests/Tx14Test.php create mode 100644 tests/Tx15Test.php create mode 100644 tests/fixtures/tx14.json create mode 100644 tests/fixtures/tx15.json diff --git a/README.md b/README.md index cbd660d..30be923 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ $TxHookParser = new TxHookParser($tx); $hooks = $TxHookParser->hooks(); # List of all accounts that are affected by hooks in transaction $accounts = $TxHookParser->accounts(); -# List of hooks by account +# List of hooks by account* $accountHooks = $TxHookParser->accountHooks('raddress...'); # List of accounts by hook $hookAccounts = $TxHookParser->hookAccounts('5EDF6...2DC77'); @@ -61,20 +61,25 @@ $destroyedHooks = $TxHookParser->destroyedHooks(); # Check if specific hook is destroyed $isDestroyed = $TxHookParser->isHookDestroyed('5EDF6...2DC77'); -# List of uninstalled hooks (eg. SetHook transaction) +# List of uninstalled hooks* (eg. SetHook transaction) $uninstalledHooks = $TxHookParser->uninstalledHooks(); # List of uninstalled hooks with num uninstalls $uninstalledHooksStats = $TxHookParser->uninstalledHooksStats(); -# List of installed hooks (eg. SetHook transaction) +# List of installed hooks* (eg. SetHook transaction) $installedHooks = $TxHookParser->installedHooks(); # List of installed hooks with num installs $installedHooksStats = $TxHookParser->installedHooksStats(); -# List of modified hooks +# List of modified hooks* $modifiedHooks = $TxHookParser->modifiedHooks(); # Manual data lookup (lookup any combination of mapped data) $lookup = $TxHookParser->lookup('raddress...','Hook','installed'); + +# * Methods that can return multiple same hook hashes, for example if +# account has same hook on two or more positions installed, it is +# important to differentiate hook "instance" on account vs hook +# create and destroy actions. List of hooks always returns unique hashes. ``` ### HookOn field diff --git a/src/TxHookParser.php b/src/TxHookParser.php index 9796858..c3bbc99 100644 --- a/src/TxHookParser.php +++ b/src/TxHookParser.php @@ -46,7 +46,6 @@ private function extractHooksFromEmitDetails(): void ($this->tx->TransactionType == 'EmitFailure' ? 'emitfail':'emitsuccess'), ); } - //dd($this->tx->EmitDetails); } private function extractHooksFromMeta(): void @@ -94,8 +93,9 @@ private function extractHooksFromMeta(): void ); if(count($parsed['added'])) { foreach($parsed['added'] as $h => $hv) { + $h = \explode('_',$h); $this->addHook( - $h, + $h[0], $AffectedNode->ModifiedNode->FinalFields->Account, //affected account 'Hook', 'installed' @@ -105,8 +105,9 @@ private function extractHooksFromMeta(): void if(count($parsed['removed'])) { foreach($parsed['removed'] as $h => $hv) { + $h = \explode('_',$h); $this->addHook( - $h, + $h[0], $AffectedNode->ModifiedNode->FinalFields->Account, //affected account 'Hook', 'uninstalled' @@ -116,26 +117,27 @@ private function extractHooksFromMeta(): void if(count($parsed['modified'])) { foreach($parsed['modified'] as $h => $hv) { + $h = \explode('_',$h); $this->addHook( - $h, + $h[0], $AffectedNode->ModifiedNode->FinalFields->Account, //affected account 'Hook', 'modified' ); } } - - //dd($parsed); - /*foreach($AffectedNode->ModifiedNode->FinalFields->Hooks as $hook) { - if(isset($hook->Hook->HookHash)) { + //dd($parsed['unmodified']); + if(count($parsed['unmodified'])) { + foreach($parsed['unmodified'] as $h => $hv) { + $h = \explode('_',$h); $this->addHook( - $hook->Hook->HookHash, + $h[0], $AffectedNode->ModifiedNode->FinalFields->Account, //affected account 'Hook', - 'updated' + 'unmodified' ); } - }*/ + } break; } } @@ -198,31 +200,59 @@ private function hookChangesFromModifiedHookNode(?array $prev, ?array $final, bo //flag to indicate modification of hook (prev does not exist in modified node) //ledger does not include previous fields when there is no changes $is_modify = !$prevFieldsSet; - + $prev = $prev === null?[]:$prev; $final = $final === null?[]:$final; - + $r = ['added' => [], 'removed' => [], 'unmodified' => [], 'modified' => []]; $tracker = []; + $postracker = ['prev' => [],'final' => []]; + + # POSTRACKER, eg hook index per hook, each first hook has index of 0 + # if there is two same hook hashes they will have indexes 0 and 1 + # Differentiate same hooks in different positions + foreach($prev as $p) { + if(!isset($p->Hook->HookHash)) continue; + if(!isset($postracker['prev'][$p->Hook->HookHash])) + $postracker['prev'][$p->Hook->HookHash] = -1; + $postracker['prev'][$p->Hook->HookHash]++; + } + + foreach($final as $p) { + if(!isset($p->Hook->HookHash)) continue; + if(!isset($postracker['final'][$p->Hook->HookHash])) + $postracker['final'][$p->Hook->HookHash] = -1; + $postracker['final'][$p->Hook->HookHash]++; + } + # POSTRACKER END foreach($prev as $p) { if(!isset($p->Hook->HookHash)) continue; $h = $p->Hook->HookHash; + //Index: + $hi = $postracker['prev'][$h]; + $postracker['prev'][$h]--; //one index exausted + //Index end $contents = $this->normalizeHookNode($p->Hook); - $tracker[$h] = ['state' => 1, 'hsh' => [\json_encode($contents)]]; + $tracker[$h.'_'.$hi] = ['state' => 1, 'hsh' => [\json_encode($contents)]]; } foreach($final as $p) { if(!isset($p->Hook->HookHash)) continue; $h = $p->Hook->HookHash; + //Index: + $hi = $postracker['final'][$h]; + $postracker['final'][$h]--; //one index exausted + //Index end $contents = $this->normalizeHookNode($p->Hook); - if(!isset($tracker[$h])) { - $tracker[$h] = ['state' => 0, 'hsh' => [\json_encode($contents)]]; + if(!isset($tracker[$h.'_'.$hi])) { + $tracker[$h.'_'.$hi] = ['state' => 0, 'hsh' => [\json_encode($contents)]]; } else { - $tracker[$h]['hsh'][] = \json_encode($contents); - $tracker[$h]['state']++; + $tracker[$h.'_'.$hi]['hsh'][] = \json_encode($contents); + $tracker[$h.'_'.$hi]['state']++; } } + foreach($tracker as $h => $data) { $state = $data['state']; if($state === 0) { @@ -335,7 +365,7 @@ public function accountHooks(string $address): array { if(!isset($this->map_account_hash[$address])) return []; - return \array_values(\array_unique($this->map_account_hash[$address])); + return \array_values($this->map_account_hash[$address]); } /** @@ -403,7 +433,7 @@ public function installedHooks(): array { if(!isset($this->map_typeevent_hashes['Hook_installed'])) return []; - return \array_values(\array_unique($this->map_typeevent_hashes['Hook_installed'])); + return \array_values($this->map_typeevent_hashes['Hook_installed']); } @@ -431,7 +461,7 @@ public function uninstalledHooks(): array { if(!isset($this->map_typeevent_hashes['Hook_uninstalled'])) return []; - return \array_values(\array_unique($this->map_typeevent_hashes['Hook_uninstalled'])); + return \array_values($this->map_typeevent_hashes['Hook_uninstalled']); } /** @@ -455,7 +485,7 @@ public function modifiedHooks(): array { if(!isset($this->map_typeevent_hashes['Hook_modified'])) return []; - return \array_values(\array_unique($this->map_typeevent_hashes['Hook_modified'])); + return \array_values($this->map_typeevent_hashes['Hook_modified']); } # Static diff --git a/tests/Tx01Test.php b/tests/Tx01Test.php index a5462aa..8cd008b 100644 --- a/tests/Tx01Test.php +++ b/tests/Tx01Test.php @@ -18,6 +18,7 @@ public function testEnableAmendment() # List of all hooks $hooks = $TxHookParser->hooks(); + $this->assertIsArray($hooks); $this->assertEquals([ '610F33B8EBF7EC795F822A454FB852156AEFE50BE0CB8326338A81CD74801864', @@ -26,13 +27,19 @@ public function testEnableAmendment() # Installed hooks $installedHooks = $TxHookParser->installedHooks(); + $this->assertIsArray($hooks); $this->assertEquals([ '5EDF6439C47C423EAC99C1061EE2A0CE6A24A58C8E8A66E4B3AF91D76772DC77', - '610F33B8EBF7EC795F822A454FB852156AEFE50BE0CB8326338A81CD74801864' + '5EDF6439C47C423EAC99C1061EE2A0CE6A24A58C8E8A66E4B3AF91D76772DC77', + '5EDF6439C47C423EAC99C1061EE2A0CE6A24A58C8E8A66E4B3AF91D76772DC77', + '610F33B8EBF7EC795F822A454FB852156AEFE50BE0CB8326338A81CD74801864', + '5EDF6439C47C423EAC99C1061EE2A0CE6A24A58C8E8A66E4B3AF91D76772DC77', + '5EDF6439C47C423EAC99C1061EE2A0CE6A24A58C8E8A66E4B3AF91D76772DC77', ], $installedHooks); $installedHooksStats = $TxHookParser->installedHooksStats(); + $this->assertEquals([ '5EDF6439C47C423EAC99C1061EE2A0CE6A24A58C8E8A66E4B3AF91D76772DC77' => 5, '610F33B8EBF7EC795F822A454FB852156AEFE50BE0CB8326338A81CD74801864' => 1 @@ -43,6 +50,7 @@ public function testEnableAmendment() # List of newly created hooks $createdHooks = $TxHookParser->createdHooks(); + $this->assertIsArray($createdHooks); $this->assertEquals([ '610F33B8EBF7EC795F822A454FB852156AEFE50BE0CB8326338A81CD74801864', @@ -51,6 +59,7 @@ public function testEnableAmendment() # List of all accounts $accounts = $TxHookParser->accounts(); + $this->assertIsArray($accounts); $this->assertEquals([ 'rwyypATD1dQxDbdQjMvrqnsHr2cQw5rjMh', @@ -62,6 +71,7 @@ public function testEnableAmendment() # Specific account $accountHooks = $TxHookParser->accountHooks('rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh'); + //dd($accountHooks); $this->assertIsArray($accountHooks); $this->assertEquals([ '5EDF6439C47C423EAC99C1061EE2A0CE6A24A58C8E8A66E4B3AF91D76772DC77', diff --git a/tests/Tx03Test.php b/tests/Tx03Test.php index 4b8a03d..6dea633 100644 --- a/tests/Tx03Test.php +++ b/tests/Tx03Test.php @@ -17,7 +17,6 @@ public function testPayment() $TxHookParser = new TxHookParser($transaction->result); # List of all hooks - $hooks = $TxHookParser->hooks(); $this->assertIsArray($hooks); $this->assertEquals([ diff --git a/tests/Tx09Test.php b/tests/Tx09Test.php index 62d6dab..99dd248 100644 --- a/tests/Tx09Test.php +++ b/tests/Tx09Test.php @@ -26,7 +26,7 @@ public function testSetHookExtractDestroyedHook() 'B2B2892A2E738D8C074C5C5B40253BDAB5E4AD3D45113144EAC5E933457AF648', 'DCA4B765D3E1372B10CC641940E4C053C23862C32E9D838D4EE98853A05C9202', ], $hooks); - + # List of newly created hooks $createdHooks = $TxHookParser->createdHooks(); $this->assertIsArray($createdHooks); @@ -50,7 +50,6 @@ public function testSetHookExtractDestroyedHook() # List of modified hooks $modifiedHooks = $TxHookParser->modifiedHooks(); - //dd($modifiedHooks); $this->assertIsArray($modifiedHooks); $this->assertEquals([ 'DCA4B765D3E1372B10CC641940E4C053C23862C32E9D838D4EE98853A05C9202', diff --git a/tests/Tx14Test.php b/tests/Tx14Test.php new file mode 100644 index 0000000..c999210 --- /dev/null +++ b/tests/Tx14Test.php @@ -0,0 +1,93 @@ +result); + + # List of all hooks + $hooks = $TxHookParser->hooks(); + $this->assertIsArray($hooks); + $this->assertEquals([ + 'ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7', + ], $hooks); + + # List of all accounts that are affected by hooks in transaction + $accounts = $TxHookParser->accounts(); + $this->assertIsArray($accounts); + $this->assertEquals([ + 'rU52Rrh1K1X7Muvx4PnpjRq8nACrfHXAy6', + ], $accounts); + + # List of newly created hooks + $createdHooks = $TxHookParser->createdHooks(); + $this->assertIsArray($createdHooks); + $this->assertEquals([], $createdHooks); + + # List of newly created hooks (detailed) + $createdHooksDetailed = $TxHookParser->createdHooksDetailed(); + $this->assertIsArray($createdHooksDetailed); + $this->assertEquals([], $createdHooksDetailed); + + # List of newly destroyed hooks + $destroyedHooks = $TxHookParser->destroyedHooks(); + $this->assertIsArray($destroyedHooks); + $this->assertEquals([], $destroyedHooks); + + # List of installed hooks + $installedHooks = $TxHookParser->installedHooks(); + $this->assertIsArray($installedHooks); + $this->assertEquals([], $installedHooks); + + # List of uninstalled hooks + $uninstalledHooks = $TxHookParser->uninstalledHooks(); + $this->assertIsArray($uninstalledHooks); + $this->assertEquals([], $uninstalledHooks); + + # Uninstalled hooks stats + $uninstalledHooksStats = $TxHookParser->uninstalledHooksStats(); + $this->assertIsArray($uninstalledHooksStats); + $this->assertEquals([], $uninstalledHooksStats); + + # List of modified hooks + # In this case two installed hooks but they are exactly the same + $modifiedHooks = $TxHookParser->modifiedHooks(); + $this->assertIsArray($modifiedHooks); + $this->assertEquals([ + 'ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7', + 'ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7', + ], $modifiedHooks); + + # List of hooks by account + $accountHooks = $TxHookParser->accountHooks('rU52Rrh1K1X7Muvx4PnpjRq8nACrfHXAy6'); + $this->assertIsArray($accountHooks); + $this->assertEquals([ + 'ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7', + 'ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7', + ], $accountHooks); + + # List of accounts by hook + $hookAccounts = $TxHookParser->hookAccounts('ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7'); + $this->assertIsArray($hookAccounts); + $this->assertEquals([ + 'rU52Rrh1K1X7Muvx4PnpjRq8nACrfHXAy6', + ], $hookAccounts); + + $this->assertFalse($TxHookParser->isHookCreated('ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7')); + + + } +} \ No newline at end of file diff --git a/tests/Tx15Test.php b/tests/Tx15Test.php new file mode 100644 index 0000000..83ff08e --- /dev/null +++ b/tests/Tx15Test.php @@ -0,0 +1,95 @@ +result); + + # List of all hooks + $hooks = $TxHookParser->hooks(); + $this->assertIsArray($hooks); + $this->assertEquals([ + 'ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7', + ], $hooks); + + # List of all accounts that are affected by hooks in transaction + $accounts = $TxHookParser->accounts(); + $this->assertIsArray($accounts); + $this->assertEquals([ + 'rU52Rrh1K1X7Muvx4PnpjRq8nACrfHXAy6', + ], $accounts); + + # List of newly created hooks + $createdHooks = $TxHookParser->createdHooks(); + $this->assertIsArray($createdHooks); + $this->assertEquals([], $createdHooks); + + # List of newly created hooks (detailed) + $createdHooksDetailed = $TxHookParser->createdHooksDetailed(); + $this->assertIsArray($createdHooksDetailed); + $this->assertEquals([], $createdHooksDetailed); + + # List of newly destroyed hooks + $destroyedHooks = $TxHookParser->destroyedHooks(); + $this->assertIsArray($destroyedHooks); + $this->assertEquals([], $destroyedHooks); + + # List of installed hooks + $installedHooks = $TxHookParser->installedHooks(); + $this->assertIsArray($installedHooks); + $this->assertEquals([ + 'ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7', + ], $installedHooks); + + # List of uninstalled hooks + $uninstalledHooks = $TxHookParser->uninstalledHooks(); + $this->assertIsArray($uninstalledHooks); + $this->assertEquals([], $uninstalledHooks); + + # Uninstalled hooks stats + $uninstalledHooksStats = $TxHookParser->uninstalledHooksStats(); + $this->assertIsArray($uninstalledHooksStats); + $this->assertEquals([], $uninstalledHooksStats); + + # List of modified hooks + # In this case no modified hooks even tho they are present in position 0 + # Both metadata are the same, this is internally unmodified hook + $modifiedHooks = $TxHookParser->modifiedHooks(); + $this->assertIsArray($modifiedHooks); + $this->assertEquals([], $modifiedHooks); + + # List of hooks by account + # In this case this account have two hooks with of same hash, one added one unmodified + $accountHooks = $TxHookParser->accountHooks('rU52Rrh1K1X7Muvx4PnpjRq8nACrfHXAy6'); + $this->assertIsArray($accountHooks); + $this->assertEquals([ + 'ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7', + 'ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7', + ], $accountHooks); + + # List of accounts by hook + $hookAccounts = $TxHookParser->hookAccounts('ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7'); + $this->assertIsArray($hookAccounts); + $this->assertEquals([ + 'rU52Rrh1K1X7Muvx4PnpjRq8nACrfHXAy6', + ], $hookAccounts); + + $this->assertFalse($TxHookParser->isHookCreated('ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7')); + + + } +} \ No newline at end of file diff --git a/tests/fixtures/tx14.json b/tests/fixtures/tx14.json new file mode 100644 index 0000000..f69ba37 --- /dev/null +++ b/tests/fixtures/tx14.json @@ -0,0 +1,139 @@ +{ + "result": { + "Account": "rU52Rrh1K1X7Muvx4PnpjRq8nACrfHXAy6", + "Fee": "128548", + "Flags": 0, + "Hooks": [ + { + "Hook": { + "CreateCode": "0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22", + "Flags": 1, + "HookApiVersion": 0, + "HookGrants": [ + { + "HookGrant": { + "HookHash": "78CAF69EEE950A6C55A450AC2A980DE434D624CD1B13148E007E28B7B6461CC8" + } + } + ], + "HookNamespace": "3963ADEB1B0E8934C0963680531202FD511FF1E16D5864402C2DA63861C420A8", + "HookOn": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFE", + "HookParameters": [ + { + "HookParameter": { + "HookParameterName": "ABCDEF12", + "HookParameterValue": "12345678" + } + } + ] + } + } + ], + "LastLedgerSequence": 9468982, + "Memos": [ + { + "Memo": { + "MemoData": "54657374206D656D6F", + "MemoType": "4465736372697074696F6E" + } + } + ], + "NetworkID": 21338, + "Sequence": 8111203, + "SigningPubKey": "ED8F72161BFEC9C5816B4DEC6E787B98760FBD5703C42AEDD44D3A1020F33561DD", + "TransactionType": "SetHook", + "TxnSignature": "A0070A62C9A01517506D617B11833516208D4BF91592338079D55061DC23742146138FA6C877F9E40B3DE81A781140CD617731AC8B64A0FEC696532A18183F04", + "ctid": "C0907C240000535A", + "date": 756812002, + "hash": "3C64927DF28615DC64554FC21DA137F2707C0C367386E15797583ECEF04996F5", + "inLedger": 9468964, + "ledger_index": 9468964, + "meta": { + "AffectedNodes": [ + { + "ModifiedNode": { + "FinalFields": { + "Account": "rU52Rrh1K1X7Muvx4PnpjRq8nACrfHXAy6", + "Flags": 0, + "Hooks": [ + { + "Hook": { + "Flags": 0, + "HookGrants": [ + { + "HookGrant": { + "HookHash": "78CAF69EEE950A6C55A450AC2A980DE434D624CD1B13148E007E28B7B6461CC8" + } + } + ], + "HookHash": "ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7", + "HookNamespace": "3963ADEB1B0E8934C0963680531202FD511FF1E16D5864402C2DA63861C420A8", + "HookOn": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFE", + "HookParameters": [ + { + "HookParameter": { + "HookParameterName": "ABCDEF12", + "HookParameterValue": "12345678" + } + } + ] + } + }, + { + "Hook": { + "Flags": 0, + "HookGrants": [ + { + "HookGrant": { + "HookHash": "78CAF69EEE950A6C55A450AC2A980DE434D624CD1B13148E007E28B7B6461CC8" + } + } + ], + "HookHash": "ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7", + "HookNamespace": "3963ADEB1B0E8934C0963680531202FD511FF1E16D5864402C2DA63861C420A8", + "HookOn": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFE", + "HookParameters": [ + { + "HookParameter": { + "HookParameterName": "ABCDEF12", + "HookParameterValue": "12345678" + } + } + ] + } + } + ], + "OwnerNode": "0" + }, + "LedgerEntryType": "Hook", + "LedgerIndex": "441FF305E743C9837317570B2D1D1F6B20793B273C099AD4D824DADA3D3863D1" + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rU52Rrh1K1X7Muvx4PnpjRq8nACrfHXAy6", + "AccountIndex": "16b8", + "Balance": "9934997770", + "EmailHash": "1D1382344586ECFF844DACFF698C2EFB", + "Flags": 0, + "MintedNFTokens": 6, + "OwnerCount": 7, + "Sequence": 8111204 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "5093B928E9075DCEFF711C84CB6C46A5A3753025B73510A79F631FE6834A03DE", + "PreviousFields": { + "Balance": "9935126318", + "Sequence": 8111203 + } + } + } + ], + "TransactionIndex": 0, + "TransactionResult": "tesSUCCESS" + }, + "status": "success", + "validated": true + } +} \ No newline at end of file diff --git a/tests/fixtures/tx15.json b/tests/fixtures/tx15.json new file mode 100644 index 0000000..7da5b64 --- /dev/null +++ b/tests/fixtures/tx15.json @@ -0,0 +1,209 @@ +{ + "result": { + "Account": "rU52Rrh1K1X7Muvx4PnpjRq8nACrfHXAy6", + "Fee": "257056", + "Hooks": [ + { + "Hook": { + "CreateCode": "0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22", + "Flags": 1, + "HookApiVersion": 0, + "HookGrants": [ + { + "HookGrant": { + "HookHash": "78CAF69EEE950A6C55A450AC2A980DE434D624CD1B13148E007E28B7B6461CC8" + } + } + ], + "HookNamespace": "3963ADEB1B0E8934C0963680531202FD511FF1E16D5864402C2DA63861C420A8", + "HookOn": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFE", + "HookParameters": [ + { + "HookParameter": { + "HookParameterName": "ABCDEF12", + "HookParameterValue": "12345678" + } + } + ] + } + }, + { + "Hook": { + "CreateCode": "0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22", + "Flags": 1, + "HookApiVersion": 0, + "HookGrants": [ + { + "HookGrant": { + "HookHash": "78CAF69EEE950A6C55A450AC2A980DE434D624CD1B13148E007E28B7B6461CC8" + } + } + ], + "HookNamespace": "3963ADEB1B0E8934C0963680531202FD511FF1E16D5864402C2DA63861C420A8", + "HookOn": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFE", + "HookParameters": [ + { + "HookParameter": { + "HookParameterName": "ABCDEF12", + "HookParameterValue": "12345678" + } + } + ] + } + } + ], + "LastLedgerSequence": 9443192, + "Memos": [ + { + "Memo": { + "MemoData": "54657374206D656D6F", + "MemoType": "4465736372697074696F6E" + } + } + ], + "NetworkID": 21338, + "Sequence": 8111180, + "SigningPubKey": "ED8F72161BFEC9C5816B4DEC6E787B98760FBD5703C42AEDD44D3A1020F33561DD", + "TransactionType": "SetHook", + "TxnSignature": "70D7E047F30759111903DEF375AA38C060869CB897E6A8E0F107F0C075B0D349C86DEEFB722F973A8F956A449A79132DDC3FF93279887CACE8854304750C5A04", + "ctid": "C09017660000535A", + "date": 756734211, + "hash": "B3B0A6BAF2D3D25BFC397E6B65F83BD0A3BE7FE2DB07941F89B9A555DB60F2D9", + "inLedger": 9443174, + "ledger_index": 9443174, + "meta": { + "AffectedNodes": [ + { + "ModifiedNode": { + "FinalFields": { + "Account": "rU52Rrh1K1X7Muvx4PnpjRq8nACrfHXAy6", + "Flags": 0, + "Hooks": [ + { + "Hook": { + "Flags": 0, + "HookGrants": [ + { + "HookGrant": { + "HookHash": "78CAF69EEE950A6C55A450AC2A980DE434D624CD1B13148E007E28B7B6461CC8" + } + } + ], + "HookHash": "ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7", + "HookNamespace": "3963ADEB1B0E8934C0963680531202FD511FF1E16D5864402C2DA63861C420A8", + "HookOn": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFE", + "HookParameters": [ + { + "HookParameter": { + "HookParameterName": "ABCDEF12", + "HookParameterValue": "12345678" + } + } + ] + } + }, + { + "Hook": { + "Flags": 0, + "HookGrants": [ + { + "HookGrant": { + "HookHash": "78CAF69EEE950A6C55A450AC2A980DE434D624CD1B13148E007E28B7B6461CC8" + } + } + ], + "HookHash": "ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7", + "HookNamespace": "3963ADEB1B0E8934C0963680531202FD511FF1E16D5864402C2DA63861C420A8", + "HookOn": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFE", + "HookParameters": [ + { + "HookParameter": { + "HookParameterName": "ABCDEF12", + "HookParameterValue": "12345678" + } + } + ] + } + } + ], + "OwnerNode": "0" + }, + "LedgerEntryType": "Hook", + "LedgerIndex": "441FF305E743C9837317570B2D1D1F6B20793B273C099AD4D824DADA3D3863D1", + "PreviousFields": { + "Hooks": [ + { + "Hook": { + "Flags": 0, + "HookGrants": [ + { + "HookGrant": { + "HookHash": "78CAF69EEE950A6C55A450AC2A980DE434D624CD1B13148E007E28B7B6461CC8" + } + } + ], + "HookHash": "ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7", + "HookNamespace": "3963ADEB1B0E8934C0963680531202FD511FF1E16D5864402C2DA63861C420A8", + "HookOn": "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFE", + "HookParameters": [ + { + "HookParameter": { + "HookParameterName": "ABCDEF12", + "HookParameterValue": "12345678" + } + } + ] + } + } + ] + } + } + }, + { + "ModifiedNode": { + "FinalFields": { + "Account": "rU52Rrh1K1X7Muvx4PnpjRq8nACrfHXAy6", + "AccountIndex": "16b8", + "Balance": "9995457584", + "Flags": 0, + "OwnerCount": 6, + "Sequence": 8111181 + }, + "LedgerEntryType": "AccountRoot", + "LedgerIndex": "5093B928E9075DCEFF711C84CB6C46A5A3753025B73510A79F631FE6834A03DE", + "PreviousFields": { + "Balance": "9995714640", + "OwnerCount": 3, + "Sequence": 8111180 + } + } + }, + { + "ModifiedNode": { + "FinalFields": { + "CreateCode": "0061736D01000000011C0460057F7F7F7F7F017E60037F7F7E017E60027F7F017F60017F017E02230303656E76057472616365000003656E7606616363657074000103656E76025F670002030201030503010002062B077F0141B088040B7F004180080B7F0041A6080B7F004180080B7F0041B088040B7F0041000B7F0041010B07080104686F6F6B00030AC4800001C0800001017F230041106B220124002001200036020C41920841134180084112410010001A410022002000420010011A41012200200010021A200141106A240042000B0B2C01004180080B254163636570742E633A2043616C6C65642E00224163636570742E633A2043616C6C65642E22", + "Fee": "32", + "Flags": 0, + "HookApiVersion": 0, + "HookHash": "ACD3E29170EB82FFF9F31A067566CD15F3A328F873F34A5D9644519C33D55EB7", + "HookNamespace": "4FF9961269BF7630D32E15276569C94470174A5DA79FA567C0F62251AA9A36B9", + "HookOn": "000000000000000000000000000000000000000000000000000000003E3FF5BE", + "HookParameters": [], + "HookSetTxnID": "F82EB3F197C4FD7FDE5D70C0468E3684276DD377CB245D13EB4B483A0FD24EC6", + "ReferenceCount": "1e5" + }, + "LedgerEntryType": "HookDefinition", + "LedgerIndex": "B2480451A57E642C7B4E6B259F0C9796A0F2CA8E748CE537D806161BEAB6E036", + "PreviousFields": { + "ReferenceCount": "1e4" + } + } + } + ], + "TransactionIndex": 0, + "TransactionResult": "tesSUCCESS" + }, + "status": "success", + "validated": true + } +} \ No newline at end of file