diff --git a/modules/abstract-substrate/src/abstractSubstrateCoin.ts b/modules/abstract-substrate/src/abstractSubstrateCoin.ts index 8e47d0ef72..fba971fdec 100644 --- a/modules/abstract-substrate/src/abstractSubstrateCoin.ts +++ b/modules/abstract-substrate/src/abstractSubstrateCoin.ts @@ -157,6 +157,13 @@ export class SubstrateCoin extends BaseCoin { if (prebuildMaterial && typeof factory.material === 'function') { factory.material(prebuildMaterial); } + // Token enablement (preApproveAsset) transactions have no destination address — they are + // self-transactions signed by the wallet. Skip transfer recipient validation, consistent + // with how XRP and Algo handle enabletoken in their verifyTransaction implementations. + if (txParams.type === 'enabletoken') { + return true; + } + const txBuilder = factory.from(txPrebuild.txHex) as unknown as NativeTransferBuilder; const txTo: string = txBuilder['_to']; const txAmount: string = txBuilder['_amount']; diff --git a/modules/sdk-coin-polyx/test/unit/polyx.ts b/modules/sdk-coin-polyx/test/unit/polyx.ts index e85af71216..0db9b3eb46 100644 --- a/modules/sdk-coin-polyx/test/unit/polyx.ts +++ b/modules/sdk-coin-polyx/test/unit/polyx.ts @@ -275,6 +275,30 @@ describe('Polyx:', function () { }); }); + describe('token enablement (preApproveAsset) transaction', function () { + it('should return true for enabletoken type with recipients (wallet root address)', async function () { + // buildTokenEnablements sets recipients[0].address = wallet rootAddress and type = 'enabletoken'. + // verifyTransaction must short-circuit before the _to check since preApproveAsset has no destination. + const walletAddress = '5F8jxKE81GhFrphyfMFr5UjeAz5wS4AaZFmeFPnf8wTetD72'; + const result = await baseCoin.verifyTransaction({ + txPrebuild: { txHex: rawTx.preApproveAsset.signed }, + txParams: { + type: 'enabletoken', + recipients: [{ address: walletAddress, amount: '0', tokenName: 'tpolyx:sometoken' }], + }, + }); + result.should.be.true(); + }); + + it('should return true for enabletoken type with no recipients', async function () { + const result = await baseCoin.verifyTransaction({ + txPrebuild: { txHex: rawTx.preApproveAsset.signed }, + txParams: { type: 'enabletoken' }, + }); + result.should.be.true(); + }); + }); + describe('v8 transfer with coinSpecific.material', function () { const v8Amount = '1000000'; const v8Receiver = accounts.account2;