Skip to content

Commit d713150

Browse files
authored
Merge pull request #6145 from BitGo/WIN-5425-2
fix(sdk-coin-polyx): fix cdd builder
2 parents 7090895 + f9c23bc commit d713150

File tree

9 files changed

+325
-21
lines changed

9 files changed

+325
-21
lines changed

modules/abstract-substrate/src/lib/transaction.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ import { DEFAULT_SUBSTRATE_PREFIX } from './constants';
2121

2222
export class Transaction extends BaseTransaction {
2323
protected _substrateTransaction: UnsignedTransaction;
24-
private _signedTransaction?: string;
25-
private _registry: TypeRegistry;
26-
private _chainName: string;
27-
private _sender: string;
24+
protected _signedTransaction?: string;
25+
protected _registry: TypeRegistry;
26+
protected _chainName: string;
27+
protected _sender: string;
2828

2929
private static FAKE_SIGNATURE = `0x${Buffer.from(new Uint8Array(256).fill(1)).toString('hex')}`;
3030

@@ -128,6 +128,7 @@ export class Transaction extends BaseTransaction {
128128

129129
/** @inheritdoc */
130130
toJson(): TxData {
131+
console.log('Transaction toJson called in substrate Transaction class');
131132
if (!this._substrateTransaction) {
132133
throw new InvalidTransactionError('Empty transaction');
133134
}

modules/abstract-substrate/src/lib/transactionBuilder.ts

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ import { Transaction } from './transaction';
2727
import { BaseTransactionSchema, SignedTransactionSchema, SigningPayloadTransactionSchema } from './txnSchema';
2828
import utils from './utils';
2929

30-
export abstract class TransactionBuilder extends BaseTransactionBuilder {
31-
protected _transaction: Transaction;
30+
export abstract class TransactionBuilder<
31+
TMethod = TxMethod,
32+
TTransaction extends Transaction = Transaction
33+
> extends BaseTransactionBuilder {
34+
protected _transaction: TTransaction;
3235
protected _keyPair: KeyPair;
3336
protected _signature?: string;
3437
protected _sender: string;
@@ -39,7 +42,7 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
3942
protected _tip?: number;
4043
protected _eraPeriod?: number;
4144
protected _registry: TypeRegistry;
42-
protected _method?: TxMethod;
45+
protected _method?: TMethod;
4346
protected _material: Material;
4447
// signatures that will be used to sign a transaction when building
4548
// not the same as the _signatures in transaction which is the signature in
@@ -48,7 +51,7 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
4851

4952
constructor(_coinConfig: Readonly<CoinConfig>) {
5053
super(_coinConfig);
51-
this._transaction = new Transaction(_coinConfig);
54+
this._transaction = new Transaction(_coinConfig) as TTransaction;
5255
}
5356

5457
/**
@@ -134,7 +137,7 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
134137
return this;
135138
}
136139

137-
private method(method: TxMethod): this {
140+
private method(method: TMethod): this {
138141
this._method = method;
139142
return this;
140143
}
@@ -154,17 +157,17 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
154157
}
155158

156159
/** @inheritdoc */
157-
protected get transaction(): Transaction {
160+
protected get transaction(): TTransaction {
158161
return this._transaction;
159162
}
160163

161164
/** @inheritdoc */
162-
protected set transaction(transaction: Transaction) {
165+
protected set transaction(transaction: TTransaction) {
163166
this._transaction = transaction;
164167
}
165168

166169
/** @inheritdoc */
167-
protected fromImplementation(rawTransaction: string): Transaction {
170+
protected fromImplementation(rawTransaction: string): TTransaction {
168171
const decodedTxn = decode(rawTransaction, {
169172
metadataRpc: this._material.metadata,
170173
registry: this._registry,
@@ -186,7 +189,7 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
186189
if (decodedTxn.tip) {
187190
this.fee({ amount: `${decodedTxn.tip}`, type: 'tip' });
188191
}
189-
this.method(decodedTxn.method as unknown as TxMethod);
192+
this.method(decodedTxn.method as unknown as TMethod);
190193
return this._transaction;
191194
}
192195

@@ -197,7 +200,7 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
197200
}
198201

199202
/** @inheritdoc */
200-
protected async buildImplementation(): Promise<Transaction> {
203+
protected async buildImplementation(): Promise<TTransaction> {
201204
this.transaction.setTransaction(this.buildTransaction());
202205
this.transaction.transactionType(this.transactionType);
203206
this.transaction.registry(this._registry);
@@ -320,7 +323,7 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
320323
}
321324

322325
/** @inheritdoc */
323-
validateTransaction(_: Transaction): void {
326+
validateTransaction(_: TTransaction): void {
324327
this.validateBaseFields(
325328
this._sender,
326329
this._blockNumber,
@@ -382,7 +385,7 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
382385
}
383386

384387
/** @inheritdoc */
385-
protected signImplementation({ key }: BaseKey): Transaction {
388+
protected signImplementation({ key }: BaseKey): TTransaction {
386389
this._keyPair = new KeyPair({ prv: key });
387390
return this._transaction;
388391
}

modules/sdk-coin-polyx/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
"@bitgo/abstract-substrate": "^1.4.9",
4444
"@substrate/txwrapper-core": "7.5.2",
4545
"@substrate/txwrapper-polkadot": "7.5.2",
46+
"@polkadot/keyring": "13.3.1",
4647
"@bitgo/sdk-core": "^33.2.0",
4748
"@bitgo/statics": "^52.2.0",
4849
"bignumber.js": "^9.1.2",
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
11
import { Args } from '@substrate/txwrapper-core';
2+
import { Interface } from '@bitgo/abstract-substrate';
3+
import { DecodedUnsignedTx } from '@substrate/txwrapper-core/lib/types';
24

35
export interface RegisterDidWithCDDArgs extends Args {
46
targetAccount: string;
57
secondaryKeys: [];
68
expiry: null;
79
}
10+
11+
export interface TxMethod extends Omit<Interface.TxMethod, 'args'> {
12+
args:
13+
| Interface.TransferArgs
14+
| Interface.TransferAllArgs
15+
| Interface.AddStakeArgs
16+
| Interface.RemoveStakeArgs
17+
| RegisterDidWithCDDArgs;
18+
}
19+
20+
export interface DecodedTx extends Omit<DecodedUnsignedTx, 'method'> {
21+
method: TxMethod;
22+
}

modules/sdk-coin-polyx/src/lib/registerDidWithCDDBuilder.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
import { TransactionBuilder, Interface } from '@bitgo/abstract-substrate';
1+
import { TransactionBuilder, Interface, utils } from '@bitgo/abstract-substrate';
22
import { DecodedSignedTx, DecodedSigningPayload, defineMethod, UnsignedTransaction } from '@substrate/txwrapper-core';
33
import { BaseCoin as CoinConfig } from '@bitgo/statics';
44
import { TransactionType, BaseAddress, InvalidTransactionError } from '@bitgo/sdk-core';
5-
import { RegisterDidWithCDDArgs } from './iface';
5+
import { RegisterDidWithCDDArgs, TxMethod } from './iface';
66
import { RegisterDidWithCDDTransactionSchema } from './txnSchema';
7+
import { Transaction } from './transaction';
78

8-
export class RegisterDidWithCDDBuilder extends TransactionBuilder {
9+
export class RegisterDidWithCDDBuilder extends TransactionBuilder<TxMethod, Transaction> {
910
protected _to: string;
11+
protected _method: TxMethod;
1012

1113
constructor(_coinConfig: Readonly<CoinConfig>) {
1214
super(_coinConfig);
15+
this._transaction = new Transaction(_coinConfig);
1316
}
1417

1518
protected get transactionType(): TransactionType {
@@ -41,6 +44,18 @@ export class RegisterDidWithCDDBuilder extends TransactionBuilder {
4144
return this;
4245
}
4346

47+
/** @inheritdoc */
48+
protected fromImplementation(rawTransaction: string): Transaction {
49+
const tx = super.fromImplementation(rawTransaction);
50+
if (this._method?.name === Interface.MethodNames.RegisterDidWithCDD) {
51+
const txMethod = this._method.args as RegisterDidWithCDDArgs;
52+
this.to({ address: utils.decodeSubstrateAddress(txMethod.targetAccount, this.getAddressFormat()) });
53+
} else {
54+
throw new InvalidTransactionError(`Invalid Transaction Type: ${this._method?.name}. Expected transferWithMemo`);
55+
}
56+
return tx;
57+
}
58+
4459
/** @inheritdoc */
4560
validateDecodedTransaction(decodedTxn: DecodedSigningPayload | DecodedSignedTx, rawTransaction?: string): void {
4661
if (decodedTxn.method?.name === Interface.MethodNames.RegisterDidWithCDD) {
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import { Transaction as SubstrateTransaction, Interface, utils, KeyPair } from '@bitgo/abstract-substrate';
2+
import { InvalidTransactionError, TransactionType } from '@bitgo/sdk-core';
3+
import { construct, decode } from '@substrate/txwrapper-polkadot';
4+
import { decodeAddress } from '@polkadot/keyring';
5+
import { DecodedTx, RegisterDidWithCDDArgs } from './iface';
6+
7+
export class Transaction extends SubstrateTransaction {
8+
/** @inheritdoc */
9+
toJson(): Interface.TxData {
10+
console.log('Transaction toJson called in polyx Transaction class');
11+
if (!this._substrateTransaction) {
12+
throw new InvalidTransactionError('Empty transaction');
13+
}
14+
15+
const decodedTx = decode(this._substrateTransaction, {
16+
metadataRpc: this._substrateTransaction.metadataRpc,
17+
registry: this._registry,
18+
isImmortalEra: utils.isZeroHex(this._substrateTransaction.era),
19+
}) as unknown as DecodedTx;
20+
21+
const result: Interface.TxData = {
22+
id: construct.txHash(this.toBroadcastFormat()),
23+
sender: decodedTx.address,
24+
referenceBlock: decodedTx.blockHash,
25+
blockNumber: decodedTx.blockNumber,
26+
genesisHash: decodedTx.genesisHash,
27+
nonce: decodedTx.nonce,
28+
specVersion: decodedTx.specVersion,
29+
transactionVersion: decodedTx.transactionVersion,
30+
eraPeriod: decodedTx.eraPeriod,
31+
chainName: this._chainName,
32+
tip: decodedTx.tip ? Number(decodedTx.tip) : 0,
33+
};
34+
35+
const txMethod = decodedTx.method.args;
36+
if (this.type === TransactionType.WalletInitialization) {
37+
const { targetAccount } = txMethod as RegisterDidWithCDDArgs;
38+
const keypairDest = new KeyPair({
39+
pub: Buffer.from(decodeAddress(targetAccount)).toString('hex'),
40+
});
41+
result.to = keypairDest.getAddress(this.getAddressFormat());
42+
} else {
43+
super.toJson();
44+
}
45+
46+
return result;
47+
}
48+
49+
/**
50+
* Load the input and output data on this transaction.
51+
*/
52+
loadInputsAndOutputs(): void {
53+
super.loadInputsAndOutputs();
54+
55+
const decodedTx = decode(this._substrateTransaction, {
56+
metadataRpc: this._substrateTransaction.metadataRpc,
57+
registry: this._registry,
58+
isImmortalEra: utils.isZeroHex(this._substrateTransaction.era),
59+
}) as unknown as DecodedTx;
60+
61+
if (this.type === TransactionType.WalletInitialization) {
62+
this.decodeInputsAndOutputsForRegisterDidWithCDD(decodedTx);
63+
}
64+
}
65+
66+
private decodeInputsAndOutputsForRegisterDidWithCDD(decodedTx: DecodedTx) {
67+
const txMethod = decodedTx.method.args as RegisterDidWithCDDArgs;
68+
const keypairDest = new KeyPair({
69+
pub: Buffer.from(decodeAddress(txMethod.targetAccount)).toString('hex'),
70+
});
71+
const to = keypairDest.getAddress(this.getAddressFormat());
72+
const value = '0';
73+
const from = decodedTx.address;
74+
75+
this._inputs.push({
76+
address: from,
77+
value,
78+
coin: this._coinConfig.name,
79+
});
80+
81+
this._outputs.push({
82+
address: to,
83+
value,
84+
coin: this._coinConfig.name,
85+
});
86+
}
87+
}

modules/sdk-coin-polyx/src/lib/transactionBuilderFactory.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import { TransferBuilder } from './transferBuilder';
55
import { RegisterDidWithCDDBuilder } from './registerDidWithCDDBuilder';
66
import utils from './utils';
77
import { Interface, SingletonRegistry, TransactionBuilder } from './';
8+
import { TxMethod } from './iface';
9+
import { Transaction as BaseTransaction } from '@bitgo/abstract-substrate';
10+
import { Transaction as PolyxTransaction } from './transaction';
11+
12+
export type SupportedTransaction = BaseTransaction | PolyxTransaction;
813

914
export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
1015
protected _material: Interface.Material;
@@ -26,7 +31,7 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
2631
throw new NotImplementedError(`walletInitialization for ${this._coinConfig.name} not implemented`);
2732
}
2833

29-
from(rawTxn: string): TransactionBuilder {
34+
from(rawTxn: string): TransactionBuilder<TxMethod, SupportedTransaction> {
3035
const builder = this.getBuilder(rawTxn);
3136
builder.from(rawTxn);
3237
return builder;
@@ -37,7 +42,7 @@ export class TransactionBuilderFactory extends BaseTransactionBuilderFactory {
3742
return this;
3843
}
3944

40-
private getBuilder(rawTxn: string): TransactionBuilder {
45+
private getBuilder(rawTxn: string): TransactionBuilder<TxMethod, SupportedTransaction> {
4146
const registry = SingletonRegistry.getInstance(this._material);
4247
const decodedTxn = decode(rawTxn, {
4348
metadataRpc: this._material.metadata,

modules/sdk-coin-polyx/test/resources/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ export const mockTssSignature =
55
'aadae7fa1f53e7a5c900b330ff71bee6782cf3c29a2c6f9599162381cd021ad581c74ded89f49ec79adefed64af8ff16649553523dda9cb4f017cbf15681e50e';
66

77
export const accounts = {
8+
cddProvider: {
9+
secretKey:
10+
'360dcfad8fbe6d514e27866ce134fcc458bc450dd2f03600b0a646ec8f5b40245a9f5ba5f51de3a38b1ee7f7e91dc9e844696d7da545d78a14b1635244e34d2a',
11+
publicKey: '5a9f5ba5f51de3a38b1ee7f7e91dc9e844696d7da545d78a14b1635244e34d2a',
12+
address: '5E7XWJRysj27EzibT4duRxrBQT9Qfa7Z5nAAvJmvd32nhkjH',
13+
},
814
account1: {
915
secretKey:
1016
'acfa9a91ed11ecc72dc015562fcb28a4b4bbca4b74f7915119578ed4579844c8cd1293d5b2ea6d7c70689079cde9ccc3dd3f4366dff4fa2f3e46ba9ee380df57',
@@ -38,6 +44,12 @@ export const rawTx = {
3844
unsigned:
3945
'0x250105010087c8be067be02a321ad8e946a4a50d71c25b9a640d064ec577d4ef9424b90b460300943577013030303030303030303030303030303030303030303030303030303132333435a503900090d76a00070000002ace05e703aa50b48c0ccccfc8b424f7aab9a1e2c424ed12e45d20b1e8ffd0d6e5c5396f3291d2575d138b98d34eac2fc156e5280276f57a30a8e3b8fbc49bfc',
4046
},
47+
cddTransaction: {
48+
signed:
49+
'0x2d0284005a9f5ba5f51de3a38b1ee7f7e91dc9e844696d7da545d78a14b1635244e34d2a00bb9ce1ddfda6d60e8169d2cab37e57ca1b1d8592f3caacc25b80d23f4c29c1efd096c9afbd86148c12e68570bab4ed3965b3180570293ea4be6f849ba362d80345030400071460b685d82b315b70d7c7604f990a05395eab09d5e75bae5d2c519ca1b01e25e50000',
50+
unsigned:
51+
'0x90071460b685d82b315b70d7c7604f990a05395eab09d5e75bae5d2c519ca1b01e25e500004503040090d76a00070000002ace05e703aa50b48c0ccccfc8b424f7aab9a1e2c424ed12e45d20b1e8ffd0d6cbd4f0bb74e13c8c4da973b1a15c3df61ae3b82677b024ffa60faf7799d5ed4b',
52+
},
4153
};
4254

4355
export const { txVersion, specVersion, genesisHash, chainName, specName } = Networks.test.polyx;

0 commit comments

Comments
 (0)