Skip to content

Commit 87cdd0e

Browse files
committed
feat: add wasm-utxo backend for cross-chain recovery
Add wasm-utxo implementation for PSBT creation in cross-chain recovery flows, alongside the existing utxolib implementation. The wasm-utxo backend is enabled for testnet coins only, while mainnet continues to use utxolib for compatibility. Key changes: - Add support for taproot script types in cross-chain recovery - Use sequence number feffffff instead of ffffffff - Add helper functions to detect taproot chains and convert networks Co-authored-by: llm-git <llm-git@ttll.de> Ticket: BTC-2892 TICKET: BTC-2892
1 parent 9423f1d commit 87cdd0e

File tree

99 files changed

+221
-101
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

99 files changed

+221
-101
lines changed

modules/abstract-utxo/src/recovery/crossChainRecovery.ts

Lines changed: 123 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,18 @@ import { BIP32Interface, bip32 } from '@bitgo/secp256k1';
33
import { Dimensions } from '@bitgo/unspents';
44
import { BitGoBase, IWallet, Keychain, Triple, Wallet } from '@bitgo/sdk-core';
55
import { decrypt } from '@bitgo/sdk-api';
6+
import { fixedScriptWallet, utxolibCompat } from '@bitgo/wasm-utxo';
67

78
import { AbstractUtxoCoin, TransactionInfo } from '../abstractUtxoCoin';
89
import { signAndVerifyPsbt } from '../transaction/fixedScript/signPsbt';
910

11+
/**
12+
* Backend to use for PSBT creation.
13+
* - 'wasm-utxo': Use wasm-utxo for PSBT creation (default)
14+
* - 'utxolib': Use utxolib for PSBT creation (legacy)
15+
*/
16+
export type PsbtBackend = 'wasm-utxo' | 'utxolib';
17+
1018
const { unspentSum } = utxolib.bitgo;
1119
type RootWalletKeys = utxolib.bitgo.RootWalletKeys;
1220
type Unspent<TNumber extends number | bigint = number> = utxolib.bitgo.Unspent<TNumber>;
@@ -324,16 +332,40 @@ async function getPrv(xprv?: string, passphrase?: string, wallet?: IWallet | Wal
324332
return getPrv(decrypt(passphrase, encryptedPrv));
325333
}
326334

335+
const { chainCodesP2tr, chainCodesP2trMusig2 } = utxolib.bitgo;
336+
337+
type ChainCode = utxolib.bitgo.ChainCode;
338+
327339
/**
328-
* Create a sweep transaction for cross-chain recovery using PSBT
340+
* Check if a chain code is for a taproot script type
341+
*/
342+
function isTaprootChain(chain: ChainCode): boolean {
343+
return (
344+
(chainCodesP2tr as readonly number[]).includes(chain) || (chainCodesP2trMusig2 as readonly number[]).includes(chain)
345+
);
346+
}
347+
348+
/**
349+
* Convert utxolib Network to wasm-utxo network name
350+
*/
351+
function toNetworkName(network: utxolib.Network): utxolibCompat.UtxolibName {
352+
const networkName = utxolib.getNetworkName(network);
353+
if (!networkName) {
354+
throw new Error(`Invalid network`);
355+
}
356+
return networkName;
357+
}
358+
359+
/**
360+
* Create a sweep transaction for cross-chain recovery using PSBT (utxolib implementation)
329361
* @param network
330362
* @param walletKeys
331363
* @param unspents
332364
* @param targetAddress
333365
* @param feeRateSatVB
334366
* @return unsigned PSBT
335367
*/
336-
function createSweepTransaction<TNumber extends number | bigint = number>(
368+
function createSweepTransactionUtxolib<TNumber extends number | bigint = number>(
337369
network: utxolib.Network,
338370
walletKeys: RootWalletKeys,
339371
unspents: WalletUnspent<TNumber>[],
@@ -372,6 +404,91 @@ function createSweepTransaction<TNumber extends number | bigint = number>(
372404
return psbt;
373405
}
374406

407+
/**
408+
* Create a sweep transaction for cross-chain recovery using wasm-utxo
409+
* @param network
410+
* @param walletKeys
411+
* @param unspents
412+
* @param targetAddress
413+
* @param feeRateSatVB
414+
* @return unsigned PSBT
415+
*/
416+
function createSweepTransactionWasm<TNumber extends number | bigint = number>(
417+
network: utxolib.Network,
418+
walletKeys: RootWalletKeys,
419+
unspents: WalletUnspent<TNumber>[],
420+
targetAddress: string,
421+
feeRateSatVB: number
422+
): utxolib.bitgo.UtxoPsbt {
423+
const inputValue = unspentSum<bigint>(
424+
unspents.map((u) => ({ ...u, value: BigInt(u.value) })),
425+
'bigint'
426+
);
427+
428+
const networkName = toNetworkName(network);
429+
430+
// Create PSBT with wasm-utxo and add wallet inputs
431+
const wasmPsbt = fixedScriptWallet.BitGoPsbt.createEmpty(networkName, walletKeys);
432+
433+
unspents.forEach((unspent) => {
434+
const { txid, vout } = utxolib.bitgo.parseOutputId(unspent.id);
435+
const signPath: fixedScriptWallet.SignPath | undefined = isTaprootChain(unspent.chain)
436+
? { signer: 'user', cosigner: 'backup' }
437+
: undefined;
438+
439+
wasmPsbt.addWalletInput(
440+
{
441+
txid,
442+
vout,
443+
value: BigInt(unspent.value),
444+
},
445+
walletKeys,
446+
{
447+
scriptId: { chain: unspent.chain, index: unspent.index },
448+
signPath,
449+
}
450+
);
451+
});
452+
453+
// Convert wasm-utxo PSBT to utxolib PSBT for dimension calculation and output addition
454+
const psbt = utxolib.bitgo.createPsbtFromBuffer(Buffer.from(wasmPsbt.serialize()), network);
455+
456+
const vsize = Dimensions.fromPsbt(psbt)
457+
.plus(Dimensions.fromOutput({ script: utxolib.address.toOutputScript(targetAddress, network) }))
458+
.getVSize();
459+
const fee = BigInt(Math.round(vsize * feeRateSatVB));
460+
461+
const recoveryOutputScript = utxolib.address.toOutputScript(targetAddress, network);
462+
psbt.addOutput({ script: recoveryOutputScript, value: inputValue - fee });
463+
464+
return psbt;
465+
}
466+
467+
/**
468+
* Create a sweep transaction for cross-chain recovery using PSBT
469+
* @param network
470+
* @param walletKeys
471+
* @param unspents
472+
* @param targetAddress
473+
* @param feeRateSatVB
474+
* @param backend - Which backend to use for PSBT creation (default: 'wasm-utxo')
475+
* @return unsigned PSBT
476+
*/
477+
function createSweepTransaction<TNumber extends number | bigint = number>(
478+
network: utxolib.Network,
479+
walletKeys: RootWalletKeys,
480+
unspents: WalletUnspent<TNumber>[],
481+
targetAddress: string,
482+
feeRateSatVB: number,
483+
backend: PsbtBackend = 'wasm-utxo'
484+
): utxolib.bitgo.UtxoPsbt {
485+
if (backend === 'wasm-utxo') {
486+
return createSweepTransactionWasm(network, walletKeys, unspents, targetAddress, feeRateSatVB);
487+
} else {
488+
return createSweepTransactionUtxolib(network, walletKeys, unspents, targetAddress, feeRateSatVB);
489+
}
490+
}
491+
375492
type RecoverParams = {
376493
/** Wallet ID (can be v1 wallet or v2 wallet) */
377494
walletId: string;
@@ -420,12 +537,15 @@ export async function recoverCrossChain<TNumber extends number | bigint = number
420537
const feeRateSatVB = await getFeeRateSatVB(params.sourceCoin);
421538

422539
// Create PSBT for both signed and unsigned recovery
540+
// Use wasm-utxo for testnet coins only, utxolib for mainnet
541+
const backend: PsbtBackend = utxolib.isTestnet(params.sourceCoin.network) ? 'wasm-utxo' : 'utxolib';
423542
const psbt = createSweepTransaction<TNumber>(
424543
params.sourceCoin.network,
425544
walletKeys,
426545
walletUnspents,
427546
params.recoveryAddress,
428-
feeRateSatVB
547+
feeRateSatVB,
548+
backend
429549
);
430550

431551
// For unsigned recovery, return unsigned PSBT hex

modules/abstract-utxo/test/unit/fixtures/tbch/recovery/crossChainRecovery-tbsv-signed.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"version": 2,
33
"walletId": "5abacebe28d72fbd07e0b8cbba0ff39e",
4-
"txHex": "70736274ff01005302000000014b0158b39d55b07ff198dc19f2c5c36b74408204a83ab9160523f0c2111b78910000000000ffffffff0188c2f5050000000017a9149c4525e9e9fc92cdda2043d35ad699c343dbab0f87000000004f010488b21e0000000000000000004b256d3cf3524c8d7086e295a1923d6fa2f99b686699ed50084bb114495c982403a86864862a9e315221809501f2a4200cd9e057a70f9164d485d4cfbeb8e47c74048374ad864f010488b21e000000000000000000914cc440157319de14126a1a2e87ea86f3b983f923fb17693a157b721220d74c02e81e105716179975cc47afd117cae272519aafdd6bfff688e4280d384e13184f04e15f6f214f010488b21e000000000000000000da28679577f7faf0ed86164da220aa4a29c7edfb0de8bdabd97f19fd15e74bed03db2b42af97f60db6ec5a1500e246ef2107660c4fc02699ed69b82c2f3e9324ae0403a823910001012018ddf5050000000017a9141e57a925dd863a86af341037e700862bf66bf7b6872202037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e474830450221009c29a7f6f5473fd3b2b3177f0f61de0162b339342605ecadd8f04b39bca9139802207937a1a4f66037d1d6238c5c9b2def7895af1e222bba6fab135fd83edb92feab41010304410000000104695221037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e472102658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d3978702102641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b853ae220602641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b8148374ad8600000000000000000000000000000000220602658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d39787014e15f6f21000000000000000000000000000000002206037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e471403a82391000000000000000000000000000000000000",
4+
"txHex": "70736274ff01005302000000014b0158b39d55b07ff198dc19f2c5c36b74408204a83ab9160523f0c2111b78910000000000feffffff0188c2f5050000000017a9149c4525e9e9fc92cdda2043d35ad699c343dbab0f87000000004f010488b21e0000000000000000004b256d3cf3524c8d7086e295a1923d6fa2f99b686699ed50084bb114495c982403a86864862a9e315221809501f2a4200cd9e057a70f9164d485d4cfbeb8e47c74048374ad864f010488b21e000000000000000000914cc440157319de14126a1a2e87ea86f3b983f923fb17693a157b721220d74c02e81e105716179975cc47afd117cae272519aafdd6bfff688e4280d384e13184f04e15f6f214f010488b21e000000000000000000da28679577f7faf0ed86164da220aa4a29c7edfb0de8bdabd97f19fd15e74bed03db2b42af97f60db6ec5a1500e246ef2107660c4fc02699ed69b82c2f3e9324ae0403a823910001012018ddf5050000000017a9141e57a925dd863a86af341037e700862bf66bf7b6872202037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e47483045022100a7d7b412b2da3064818a87f524038ab5a796b2fb24e72d2ec13d363271cdeb390220519d8330223adf28a3d25027ff572786f78dc941b9a82770793271192c555abe41010304410000000104695221037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e472102658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d3978702102641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b853ae220602641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b8148374ad8600000000000000000000000000000000220602658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d39787014e15f6f21000000000000000000000000000000002206037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e471403a82391000000000000000000000000000000000000",
55
"sourceCoin": "tbch",
66
"recoveryCoin": "tbsv",
77
"recoveryAmount": 99992200

modules/abstract-utxo/test/unit/fixtures/tbch/recovery/crossChainRecovery-tbsv-unsigned.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"txHex": "70736274ff01005302000000014b0158b39d55b07ff198dc19f2c5c36b74408204a83ab9160523f0c2111b78910000000000ffffffff0188c2f5050000000017a9149c4525e9e9fc92cdda2043d35ad699c343dbab0f87000000004f010488b21e0000000000000000004b256d3cf3524c8d7086e295a1923d6fa2f99b686699ed50084bb114495c982403a86864862a9e315221809501f2a4200cd9e057a70f9164d485d4cfbeb8e47c74048374ad864f010488b21e000000000000000000914cc440157319de14126a1a2e87ea86f3b983f923fb17693a157b721220d74c02e81e105716179975cc47afd117cae272519aafdd6bfff688e4280d384e13184f04e15f6f214f010488b21e000000000000000000da28679577f7faf0ed86164da220aa4a29c7edfb0de8bdabd97f19fd15e74bed03db2b42af97f60db6ec5a1500e246ef2107660c4fc02699ed69b82c2f3e9324ae0403a823910001012018ddf5050000000017a9141e57a925dd863a86af341037e700862bf66bf7b687010304410000000104695221037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e472102658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d3978702102641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b853ae220602641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b8148374ad8600000000000000000000000000000000220602658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d39787014e15f6f21000000000000000000000000000000002206037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e471403a82391000000000000000000000000000000000000",
2+
"txHex": "70736274ff01005302000000014b0158b39d55b07ff198dc19f2c5c36b74408204a83ab9160523f0c2111b78910000000000feffffff0188c2f5050000000017a9149c4525e9e9fc92cdda2043d35ad699c343dbab0f87000000004f010488b21e0000000000000000004b256d3cf3524c8d7086e295a1923d6fa2f99b686699ed50084bb114495c982403a86864862a9e315221809501f2a4200cd9e057a70f9164d485d4cfbeb8e47c74048374ad864f010488b21e000000000000000000914cc440157319de14126a1a2e87ea86f3b983f923fb17693a157b721220d74c02e81e105716179975cc47afd117cae272519aafdd6bfff688e4280d384e13184f04e15f6f214f010488b21e000000000000000000da28679577f7faf0ed86164da220aa4a29c7edfb0de8bdabd97f19fd15e74bed03db2b42af97f60db6ec5a1500e246ef2107660c4fc02699ed69b82c2f3e9324ae0403a823910001012018ddf5050000000017a9141e57a925dd863a86af341037e700862bf66bf7b687010304410000000104695221037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e472102658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d3978702102641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b853ae220602641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b8148374ad8600000000000000000000000000000000220602658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d39787014e15f6f21000000000000000000000000000000002206037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e471403a82391000000000000000000000000000000000000",
33
"walletId": "5abacebe28d72fbd07e0b8cbba0ff39e",
44
"address": "2N7VWEhmfT8CzGSW2bCVeKJ3GCwSD1nsL2V",
55
"coin": "tbch"

modules/abstract-utxo/test/unit/fixtures/tbch/recovery/crossChainRecovery-tbtc-signed.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"version": 2,
33
"walletId": "5abacebe28d72fbd07e0b8cbba0ff39e",
4-
"txHex": "70736274ff01005302000000014b0158b39d55b07ff198dc19f2c5c36b74408204a83ab9160523f0c2111b78910000000000ffffffff0188c2f5050000000017a9149c4525e9e9fc92cdda2043d35ad699c343dbab0f87000000004f010488b21e0000000000000000004b256d3cf3524c8d7086e295a1923d6fa2f99b686699ed50084bb114495c982403a86864862a9e315221809501f2a4200cd9e057a70f9164d485d4cfbeb8e47c74048374ad864f010488b21e000000000000000000914cc440157319de14126a1a2e87ea86f3b983f923fb17693a157b721220d74c02e81e105716179975cc47afd117cae272519aafdd6bfff688e4280d384e13184f04e15f6f214f010488b21e000000000000000000da28679577f7faf0ed86164da220aa4a29c7edfb0de8bdabd97f19fd15e74bed03db2b42af97f60db6ec5a1500e246ef2107660c4fc02699ed69b82c2f3e9324ae0403a823910001012018ddf5050000000017a9141e57a925dd863a86af341037e700862bf66bf7b6872202037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e474830450221009c29a7f6f5473fd3b2b3177f0f61de0162b339342605ecadd8f04b39bca9139802207937a1a4f66037d1d6238c5c9b2def7895af1e222bba6fab135fd83edb92feab41010304410000000104695221037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e472102658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d3978702102641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b853ae220602641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b8148374ad8600000000000000000000000000000000220602658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d39787014e15f6f21000000000000000000000000000000002206037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e471403a82391000000000000000000000000000000000000",
4+
"txHex": "70736274ff01005302000000014b0158b39d55b07ff198dc19f2c5c36b74408204a83ab9160523f0c2111b78910000000000feffffff0188c2f5050000000017a9149c4525e9e9fc92cdda2043d35ad699c343dbab0f87000000004f010488b21e0000000000000000004b256d3cf3524c8d7086e295a1923d6fa2f99b686699ed50084bb114495c982403a86864862a9e315221809501f2a4200cd9e057a70f9164d485d4cfbeb8e47c74048374ad864f010488b21e000000000000000000914cc440157319de14126a1a2e87ea86f3b983f923fb17693a157b721220d74c02e81e105716179975cc47afd117cae272519aafdd6bfff688e4280d384e13184f04e15f6f214f010488b21e000000000000000000da28679577f7faf0ed86164da220aa4a29c7edfb0de8bdabd97f19fd15e74bed03db2b42af97f60db6ec5a1500e246ef2107660c4fc02699ed69b82c2f3e9324ae0403a823910001012018ddf5050000000017a9141e57a925dd863a86af341037e700862bf66bf7b6872202037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e47483045022100a7d7b412b2da3064818a87f524038ab5a796b2fb24e72d2ec13d363271cdeb390220519d8330223adf28a3d25027ff572786f78dc941b9a82770793271192c555abe41010304410000000104695221037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e472102658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d3978702102641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b853ae220602641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b8148374ad8600000000000000000000000000000000220602658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d39787014e15f6f21000000000000000000000000000000002206037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e471403a82391000000000000000000000000000000000000",
55
"sourceCoin": "tbch",
66
"recoveryCoin": "tbtc",
77
"recoveryAmount": 99992200

modules/abstract-utxo/test/unit/fixtures/tbch/recovery/crossChainRecovery-tbtc-unsigned.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"txHex": "70736274ff01005302000000014b0158b39d55b07ff198dc19f2c5c36b74408204a83ab9160523f0c2111b78910000000000ffffffff0188c2f5050000000017a9149c4525e9e9fc92cdda2043d35ad699c343dbab0f87000000004f010488b21e0000000000000000004b256d3cf3524c8d7086e295a1923d6fa2f99b686699ed50084bb114495c982403a86864862a9e315221809501f2a4200cd9e057a70f9164d485d4cfbeb8e47c74048374ad864f010488b21e000000000000000000914cc440157319de14126a1a2e87ea86f3b983f923fb17693a157b721220d74c02e81e105716179975cc47afd117cae272519aafdd6bfff688e4280d384e13184f04e15f6f214f010488b21e000000000000000000da28679577f7faf0ed86164da220aa4a29c7edfb0de8bdabd97f19fd15e74bed03db2b42af97f60db6ec5a1500e246ef2107660c4fc02699ed69b82c2f3e9324ae0403a823910001012018ddf5050000000017a9141e57a925dd863a86af341037e700862bf66bf7b687010304410000000104695221037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e472102658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d3978702102641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b853ae220602641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b8148374ad8600000000000000000000000000000000220602658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d39787014e15f6f21000000000000000000000000000000002206037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e471403a82391000000000000000000000000000000000000",
2+
"txHex": "70736274ff01005302000000014b0158b39d55b07ff198dc19f2c5c36b74408204a83ab9160523f0c2111b78910000000000feffffff0188c2f5050000000017a9149c4525e9e9fc92cdda2043d35ad699c343dbab0f87000000004f010488b21e0000000000000000004b256d3cf3524c8d7086e295a1923d6fa2f99b686699ed50084bb114495c982403a86864862a9e315221809501f2a4200cd9e057a70f9164d485d4cfbeb8e47c74048374ad864f010488b21e000000000000000000914cc440157319de14126a1a2e87ea86f3b983f923fb17693a157b721220d74c02e81e105716179975cc47afd117cae272519aafdd6bfff688e4280d384e13184f04e15f6f214f010488b21e000000000000000000da28679577f7faf0ed86164da220aa4a29c7edfb0de8bdabd97f19fd15e74bed03db2b42af97f60db6ec5a1500e246ef2107660c4fc02699ed69b82c2f3e9324ae0403a823910001012018ddf5050000000017a9141e57a925dd863a86af341037e700862bf66bf7b687010304410000000104695221037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e472102658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d3978702102641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b853ae220602641ee6557561c9038242cafa7f538070d7646a969bcf6169f9950abfcfefd6b8148374ad8600000000000000000000000000000000220602658831a87322b3583515ca8725841335505755ada53ee133c70a6b4b8d39787014e15f6f21000000000000000000000000000000002206037acffd52bb7c39a4ac3d4c01af33ce0367afec45347e332edca63a38d1fb2e471403a82391000000000000000000000000000000000000",
33
"walletId": "5abacebe28d72fbd07e0b8cbba0ff39e",
44
"address": "2N7VWEhmfT8CzGSW2bCVeKJ3GCwSD1nsL2V",
55
"coin": "tbch"

0 commit comments

Comments
 (0)