Skip to content

Commit 3b423cb

Browse files
committed
Zero AMM Withdraw
1 parent ac5f51b commit 3b423cb

File tree

3 files changed

+184
-0
lines changed

3 files changed

+184
-0
lines changed

src/TxParticipantExtractor.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ public function __construct(\stdClass $tx, array $options = [])
109109
//Extract all other participants from meta
110110
$this->extractAccountsFromMeta();
111111
$this->normalizeAccounts();
112+
//Logic handlers
113+
$this->logic_detectAMMWithdraw();
114+
112115
if(isset($options['allowSpecialAccounts']) && $options['allowSpecialAccounts']) {
113116
//do not remove special accounts
114117
} else {
@@ -119,6 +122,45 @@ public function __construct(\stdClass $tx, array $options = [])
119122
//foreach($this->result as $r) {echo "'".$r."',".PHP_EOL;}exit;
120123
}
121124

125+
/**
126+
* Logic handler for AMMWithdraw
127+
* This method will detect AMM_ACCOUNT by comparing existing detected accounts.
128+
* @return void
129+
*/
130+
private function logic_detectAMMWithdraw()
131+
{
132+
if($this->tx->TransactionType != 'AMMWithdraw')
133+
return;
134+
$accounts = $this->accounts;
135+
//Check if AMM_ACCOUNT role does not exist
136+
foreach($this->accounts as $acc => $roles) {
137+
if(\in_array('AMM_ACCOUNT',$roles))
138+
return;
139+
}
140+
unset($acc);
141+
unset($roles);
142+
143+
//This is AMMWithdraw but AMM_ACCOUNT was not detected
144+
145+
unset($accounts[self::ACCOUNT_ZERO]);
146+
unset($accounts[self::ACCOUNT_ONE]);
147+
unset($accounts[self::ACCOUNT_GENESIS]);
148+
unset($accounts[self::ACCOUNT_BLACKHOLE]);
149+
unset($accounts[self::ACCOUNT_NAN]);
150+
151+
//If there is two non special accounts present, one is transaction initiator other is AMM Account - see test 45
152+
if(count($accounts) != 2) {
153+
throw new \Exception('Unhandled: unable to detect AMM_ACCOUNT in logic_detectAMMWithdraw - more than two accounts detected without obvious AMM account');
154+
//return;
155+
}
156+
157+
foreach($this->accounts as $acc => $roles) {
158+
if(!\in_array('INITIATOR',$roles)) {
159+
$this->addAccount($acc, 'AMM_ACCOUNT');
160+
}
161+
}
162+
}
163+
122164
/**
123165
* Extracts all accounts from metadata.
124166
*

tests/Tx45Test.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace XRPLWin\XRPLTxParticipantExtractor\Tests;
4+
5+
use PHPUnit\Framework\TestCase;
6+
use XRPLWin\XRPLTxParticipantExtractor\TxParticipantExtractor;
7+
8+
/***
9+
* AMMWithdraw
10+
* Mainnet. AMMWithdraw with 0 XRP yielded small amount of LPToken returned. In return its harder to find AMMAccountID
11+
* AMMAccountID is RIPPLESTATE_HIGHLIMIT_ISSUER, we need to detect it also as AMMAccountID as special logic rule detection.
12+
*/
13+
final class Tx45Test extends TestCase
14+
{
15+
public function testZeroAMMWithdrawLogicDetect()
16+
{
17+
$transaction = file_get_contents(__DIR__.'/fixtures/tx45.json');
18+
$transaction = \json_decode($transaction);
19+
$TxParticipantExtractor = new TxParticipantExtractor($transaction->result);
20+
21+
$parsedTransaction = $TxParticipantExtractor->result();
22+
$this->assertIsArray($parsedTransaction);
23+
24+
$this->assertEquals([
25+
'ro1VomW8pj9U3o93bxSHXipaSqQ1siJ5t',
26+
'rB3nE2RcnhAqUj3xYczakzvF72uW6ML9UM'
27+
], $parsedTransaction);
28+
29+
$accounts = $TxParticipantExtractor->accounts();
30+
31+
//This regular key is transaction signer
32+
$this->assertEquals([
33+
'INITIATOR',
34+
'TXSIGNER',
35+
'RIPPLESTATE_LOWLIMIT_ISSUER',
36+
'ACCOUNTROOT_ACCOUNT',
37+
], $accounts['ro1VomW8pj9U3o93bxSHXipaSqQ1siJ5t']);
38+
39+
//This is AMM AccountID
40+
$this->assertEquals([
41+
'RIPPLESTATE_HIGHLIMIT_ISSUER',
42+
'AMM_ACCOUNT',
43+
], $accounts['rB3nE2RcnhAqUj3xYczakzvF72uW6ML9UM']);
44+
45+
}
46+
}

tests/fixtures/tx45.json

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
{
2+
"result": {
3+
"Account": "ro1VomW8pj9U3o93bxSHXipaSqQ1siJ5t",
4+
"Amount": "0",
5+
"Asset": {
6+
"currency": "XRP"
7+
},
8+
"Asset2": {
9+
"currency": "5852646F67650000000000000000000000000000",
10+
"issuer": "rLqUC2eCPohYvJCEBJ77eCCqVL2uEiczjA"
11+
},
12+
"Fee": "12",
13+
"Flags": 262144,
14+
"LastLedgerSequence": 87643257,
15+
"Memos": [
16+
{
17+
"Memo": {
18+
"MemoData": "414D4D20776974686472617720696E69746961746564207669612058506D61726B65742E636F6D"
19+
}
20+
}
21+
],
22+
"Sequence": 522,
23+
"SigningPubKey": "0289DEF271D5EBAAAF202A74DEEB9C9929313EE45A97436112E1F76BEAB25D14FA",
24+
"SourceTag": 20221212,
25+
"TransactionType": "AMMWithdraw",
26+
"TxnSignature": "3045022100B0E1CB9F3FE4BC4942468692F9913FAD683E0818B4AF97BE523C860E9E91995602205DFBFDB52C36B034E6778018693E4B4473FE1A258B548B27ADCC2CFE1ADB1E4F",
27+
"ctid": "C539547100180000",
28+
"date": 767712010,
29+
"hash": "35F5EE63A28B4FAC5C106B147D8A89719ED7C1B3C4528BFEA3A42C0CC03361DE",
30+
"inLedger": 87643249,
31+
"ledger_index": 87643249,
32+
"meta": {
33+
"AffectedNodes": [
34+
{
35+
"ModifiedNode": {
36+
"FinalFields": {
37+
"Balance": {
38+
"currency": "03763B56435F1318F381128FD9A655041FCB5472",
39+
"issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji",
40+
"value": "0"
41+
},
42+
"Flags": 1114112,
43+
"HighLimit": {
44+
"currency": "03763B56435F1318F381128FD9A655041FCB5472",
45+
"issuer": "rB3nE2RcnhAqUj3xYczakzvF72uW6ML9UM",
46+
"value": "0"
47+
},
48+
"HighNode": "0",
49+
"LowLimit": {
50+
"currency": "03763B56435F1318F381128FD9A655041FCB5472",
51+
"issuer": "ro1VomW8pj9U3o93bxSHXipaSqQ1siJ5t",
52+
"value": "1000000000"
53+
},
54+
"LowNode": "0"
55+
},
56+
"LedgerEntryType": "RippleState",
57+
"LedgerIndex": "3E9E7D5F8F6DD9702D31B739CFB4BE5B467E5FFB97CD4FBE327AAEF0D4B14507",
58+
"PreviousFields": {
59+
"Balance": {
60+
"currency": "03763B56435F1318F381128FD9A655041FCB5472",
61+
"issuer": "rrrrrrrrrrrrrrrrrrrrBZbvji",
62+
"value": "0.0000001"
63+
}
64+
},
65+
"PreviousTxnID": "0DCA6D912DBB91B33456A079E6549B0868BEA40A678EDC9BC5B5A194A5B7F6F0",
66+
"PreviousTxnLgrSeq": 87254867
67+
}
68+
},
69+
{
70+
"ModifiedNode": {
71+
"FinalFields": {
72+
"Account": "ro1VomW8pj9U3o93bxSHXipaSqQ1siJ5t",
73+
"Balance": "186429485",
74+
"Flags": 0,
75+
"MessageKey": "02000000000000000000000000AD3C758F977769CB9D79CBCCECBAA2882333FA58",
76+
"OwnerCount": 6,
77+
"Sequence": 523
78+
},
79+
"LedgerEntryType": "AccountRoot",
80+
"LedgerIndex": "F588E12BE7E5F152D68F70393AB718C4FA12E8DDE631F40682BFBFD7373D9765",
81+
"PreviousFields": {
82+
"Balance": "186429497",
83+
"Sequence": 522
84+
},
85+
"PreviousTxnID": "BAF8C598E041DDF0CFF534D305BE8BFF09762CDB862D3D7A45E004EF3A18261B",
86+
"PreviousTxnLgrSeq": 87643224
87+
}
88+
}
89+
],
90+
"TransactionIndex": 24,
91+
"TransactionResult": "tesSUCCESS"
92+
},
93+
"status": "success",
94+
"validated": true
95+
}
96+
}

0 commit comments

Comments
 (0)