Skip to content

Commit f2d2088

Browse files
committed
feat(sdk-coin-icp): make memo field optional in transaction interfaces and builders
TICKET: WIN-5112
1 parent 60bb013 commit f2d2088

File tree

9 files changed

+192
-34
lines changed

9 files changed

+192
-34
lines changed

modules/sdk-coin-icp/src/lib/iface.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,13 @@ export enum Network {
3535
ID = '00000000000000020101', // ICP does not have different network IDs for mainnet and testnet
3636
}
3737

38-
//TODO make memo optional in the interface
3938
export interface IcpTransactionData {
4039
senderAddress: string;
4140
receiverAddress: string;
4241
amount: string;
4342
fee: string;
4443
senderPublicKeyHex: string;
45-
memo: number | BigInt; // memo in string is not accepted by ICP chain.
44+
memo?: number | BigInt; // memo in string is not accepted by ICP chain.
4645
transactionType: OperationType;
4746
expiryTime: number | BigInt;
4847
}
@@ -72,10 +71,9 @@ export interface IcpOperation {
7271
amount: IcpAmount;
7372
}
7473

75-
//TODO check for optional memo in the interface
7674
export interface IcpTransactionParseMetadata {
7775
created_at_time: number;
78-
memo: number | BigInt; // memo in string is not accepted by ICP chain.
76+
memo?: number | BigInt; // memo in string is not accepted by ICP chain.
7977
ingress_start?: number | BigInt; // it should be nano seconds
8078
ingress_end?: number | BigInt; // it should be nano seconds
8179
}
@@ -104,7 +102,7 @@ export interface IcpAccountIdentifier {
104102
}
105103

106104
export interface SendArgs {
107-
memo: { memo: number | BigInt };
105+
memo?: { memo: number | BigInt };
108106
payment: { receiverGets: { e8s: number } };
109107
maxFee: { e8s: number };
110108
to: { hash: Buffer };
@@ -163,7 +161,7 @@ export interface TxData {
163161
sender: string;
164162
senderPublicKey: string;
165163
recipient: string;
166-
memo: number | BigInt;
164+
memo?: number | BigInt;
167165
feeAmount: string;
168166
expirationTime: number | BigInt;
169167
type?: BitGoTransactionType;

modules/sdk-coin-icp/src/lib/transaction.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,18 @@ export class Transaction extends BaseTransaction {
9797
const transactionType = parsedTx.operations[0].type;
9898
switch (transactionType) {
9999
case OperationType.TRANSACTION:
100-
//TODO memo is optional here too, check proto def as well
101100
this._icpTransactionData = {
102101
senderAddress: parsedTx.operations[0].account.address,
103102
receiverAddress: parsedTx.operations[1].account.address,
104103
amount: parsedTx.operations[1].amount.value,
105104
fee: parsedTx.operations[2].amount.value,
106105
senderPublicKeyHex: senderPublicKeyHex,
107-
memo: parsedTx.metadata.memo,
108106
transactionType: transactionType,
109107
expiryTime: Number(parsedTx.metadata.created_at_time + (MAX_INGRESS_TTL - PERMITTED_DRIFT)),
110108
};
109+
if (parsedTx.metadata.memo !== undefined) {
110+
this._icpTransactionData.memo = parsedTx.metadata.memo;
111+
}
111112
this._utils.validateRawTransaction(this._icpTransactionData);
112113
break;
113114
default:
@@ -135,7 +136,7 @@ export class Transaction extends BaseTransaction {
135136
}
136137
switch (this._icpTransactionData.transactionType) {
137138
case OperationType.TRANSACTION:
138-
return {
139+
const txData: TxData = {
139140
id: this._id,
140141
sender: this._icpTransactionData.senderAddress,
141142
senderPublicKey: this._icpTransactionData.senderPublicKeyHex,
@@ -145,6 +146,10 @@ export class Transaction extends BaseTransaction {
145146
expirationTime: this._icpTransactionData.expiryTime,
146147
type: BitGoTransactionType.Send,
147148
};
149+
if (this._icpTransactionData.memo !== undefined) {
150+
txData.memo = this._icpTransactionData.memo;
151+
}
152+
return txData;
148153
default:
149154
throw new Error(`Unsupported transaction type: ${this._icpTransactionData.transactionType}`);
150155
}
@@ -271,10 +276,12 @@ export class Transaction extends BaseTransaction {
271276
operations: [senderOperation, receiverOperation, feeOperation],
272277
metadata: {
273278
created_at_time: args.createdAtTime.timestampNanos,
274-
memo: Number(args.memo.memo),
275279
},
276280
account_identifier_signers: accountIdentifierSigners,
277281
};
282+
if (args.memo !== undefined) {
283+
parsedTxn.metadata.memo = Number(args.memo.memo);
284+
}
278285
this.createdTimestamp = args.createdAtTime.timestampNanos;
279286
return parsedTxn;
280287
}

modules/sdk-coin-icp/src/lib/transactionBuilder.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,10 +132,12 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
132132
this._transaction = tx;
133133
const icpTransactionData = tx.icpTransactionData;
134134
this._sender = icpTransactionData.senderAddress;
135-
this._memo = icpTransactionData.memo;
136135
this._receiverId = icpTransactionData.receiverAddress;
137136
this._publicKey = icpTransactionData.senderPublicKeyHex;
138137
this._amount = icpTransactionData.amount;
138+
if (icpTransactionData.memo !== undefined) {
139+
this._memo = icpTransactionData.memo;
140+
}
139141
}
140142

141143
validateAddress(address: BaseAddress): void {

modules/sdk-coin-icp/src/lib/transferBuilder.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,10 +104,12 @@ export class TransferBuilder extends TransactionBuilder {
104104
amount: this._amount,
105105
fee: this._utils.feeData(),
106106
senderPublicKeyHex: this._publicKey,
107-
memo: this._memo,
108107
transactionType: OperationType.TRANSACTION,
109108
expiryTime: ingressEndTime,
110109
};
110+
if (this._memo !== undefined) {
111+
icpTransactionData.memo = this._memo;
112+
}
111113
this._transaction.icpTransactionData = icpTransactionData;
112114
this._transaction.icpTransaction = icpTransaction;
113115
}

modules/sdk-coin-icp/src/lib/unsignedTransactionBuilder.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,22 @@ export class UnsignedTransactionBuilder {
8989
return ingressExpiries;
9090
}
9191

92-
getSendArgs(memo: number | BigInt, created_at_time: number, amount: string, fee: string, receiver: string): SendArgs {
92+
getSendArgs(
93+
memo: number | BigInt | undefined,
94+
created_at_time: number,
95+
amount: string,
96+
fee: string,
97+
receiver: string
98+
): SendArgs {
9399
const sendArgs: SendArgs = {
94-
memo: { memo: memo },
95100
payment: { receiverGets: { e8s: Number(amount) } },
96101
maxFee: { e8s: -Number(fee) },
97102
to: { hash: Buffer.from(receiver, 'hex') },
98103
createdAtTime: { timestampNanos: Number(created_at_time) },
99104
};
105+
if (memo !== undefined) {
106+
sendArgs.memo = { memo: memo };
107+
}
100108
return sendArgs;
101109
}
102110

modules/sdk-coin-icp/src/lib/utils.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,8 +358,9 @@ export class Utils implements BaseUtils {
358358
}
359359
this.validateFee(transactionData.fee);
360360
this.validateValue(new BigNumber(transactionData.amount));
361-
//TODO check for optional memo
362-
this.validateMemo(transactionData.memo);
361+
if (transactionData.memo !== undefined) {
362+
this.validateMemo(transactionData.memo);
363+
}
363364
this.validateExpireTime(transactionData.expiryTime);
364365
}
365366

@@ -607,12 +608,14 @@ export class Utils implements BaseUtils {
607608
const SendRequestMessage = root.lookupType('SendRequest');
608609
const args = SendRequestMessage.decode(arg) as unknown as SendArgs;
609610
const transformedArgs: SendArgs = {
610-
memo: { memo: BigInt(args.memo.memo.toString()) },
611611
payment: { receiverGets: { e8s: args.payment.receiverGets.e8s } },
612612
maxFee: { e8s: args.maxFee.e8s },
613613
to: { hash: Buffer.from(args.to.hash) },
614614
createdAtTime: { timestampNanos: BigNumber(args.createdAtTime.timestampNanos.toString()).toNumber() },
615615
};
616+
if (args.memo !== undefined && args.memo !== null) {
617+
transformedArgs.memo = { memo: BigInt(args.memo?.memo?.toString()) };
618+
}
616619
return transformedArgs;
617620
}
618621

modules/sdk-coin-icp/test/resources/icp.ts

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,21 @@ export const payloadsData = {
195195
'b90002677570646174657381826b5452414e53414354494f4eb900056b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f70626361726758400a0308d20912040a02080a1a0308904e2a220a20c3d30f404955975adaba89f2e1ebc75c1f44a6a204578afce8f3780d64fe252e3a0a0880a48596eb92b599186673656e646572581dd5fc1dc4d74d4aa35d81cf345533d20548113412d32fffdcece2f68a026e696e67726573735f6578706972791b000000000000000070696e67726573735f6578706972696573811b1832d4ce93deb200',
196196
};
197197

198-
export const signatures = [
198+
export const payloadsDataWithoutMemo = {
199+
payloads: [
200+
{
201+
hex_bytes: '0a69632d726571756573743112e4b82e09b05badc6978a3bb9eb2773cf467c7c62f573b6b4df5d304a6487',
202+
account_identifier: {
203+
address: '0af815da8259ba8bb3d34fbfb2ac730f07a1adc81438d40d667d91b408b25f2f',
204+
},
205+
signature_type: 'ecdsa',
206+
},
207+
],
208+
unsigned_transaction:
209+
'b90002677570646174657381826b5452414e53414354494f4eb900056b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f706263617267583b12040a02080a1a0308904e2a220a20c3d30f404955975adaba89f2e1ebc75c1f44a6a204578afce8f3780d64fe252e3a0a0880a48596eb92b599186673656e646572581dd5fc1dc4d74d4aa35d81cf345533d20548113412d32fffdcece2f68a026e696e67726573735f6578706972791b000000000000000070696e67726573735f6578706972696573811b1832d4ce93deb200',
210+
};
211+
212+
export const Signatures = [
199213
{
200214
signing_payload: {
201215
account_identifier: { address: '0af815da8259ba8bb3d34fbfb2ac730f07a1adc81438d40d667d91b408b25f2f' },
@@ -213,9 +227,30 @@ export const signatures = [
213227
},
214228
];
215229

216-
export const signedTransaction =
230+
export const SignaturesWithoutMemo = [
231+
{
232+
signing_payload: {
233+
account_identifier: { address: '0af815da8259ba8bb3d34fbfb2ac730f07a1adc81438d40d667d91b408b25f2f' },
234+
hex_bytes: '0a69632d726571756573743112e4b82e09b05badc6978a3bb9eb2773cf467c7c62f573b6b4df5d304a6487',
235+
signature_type: 'ecdsa',
236+
},
237+
signature_type: 'ecdsa',
238+
public_key: {
239+
hex_bytes:
240+
'042ab77b959e28c4fa47fa8fb9e57cec3d66df5684d076ac2e4c5f28fd69a23dd31a59f908c8add51eab3530b4ac5d015166eaf2198c52fa9a8df7cfaeb8fdb7d4',
241+
curve_type: 'secp256k1',
242+
},
243+
hex_bytes:
244+
'5a954e35fa40b0aec27f83a8d6124b5c2f68622c5f4799bc66ff4ff994ffcad14b22dbf5a0a1438d3b812375aab16637659207e745f705f436a599a3ee2bfaac',
245+
},
246+
];
247+
248+
export const SignedTransaction =
217249
'b9000367636f6e74656e74b900066c726571756573745f747970656463616c6c6b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f70626361726758400a0308d20912040a02080a1a0308904e2a220a20c3d30f404955975adaba89f2e1ebc75c1f44a6a204578afce8f3780d64fe252e3a0a0880a48596eb92b599186673656e646572581dd5fc1dc4d74d4aa35d81cf345533d20548113412d32fffdcece2f68a026e696e67726573735f6578706972791b1832d4ce93deb2006d73656e6465725f7075626b6579d84058583056301006072a8648ce3d020106052b8104000a034200042ab77b959e28c4fa47fa8fb9e57cec3d66df5684d076ac2e4c5f28fd69a23dd31a59f908c8add51eab3530b4ac5d015166eaf2198c52fa9a8df7cfaeb8fdb7d46a73656e6465725f7369675840dee0c728fc06d2140ad84e2be5f983626114d49f51216d4070bfccbfba79041d77648bad917428a8adb9908828458488562f0d159571382b1ac50fb81d5165c9';
218250

251+
export const SignedTransactionWithoutMemo =
252+
'b9000367636f6e74656e74b900066c726571756573745f747970656463616c6c6b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f706263617267583b12040a02080a1a0308904e2a220a20c3d30f404955975adaba89f2e1ebc75c1f44a6a204578afce8f3780d64fe252e3a0a0880a48596eb92b599186673656e646572581dd5fc1dc4d74d4aa35d81cf345533d20548113412d32fffdcece2f68a026e696e67726573735f6578706972791b1832d4ce93deb2006d73656e6465725f7075626b6579d84058583056301006072a8648ce3d020106052b8104000a034200042ab77b959e28c4fa47fa8fb9e57cec3d66df5684d076ac2e4c5f28fd69a23dd31a59f908c8add51eab3530b4ac5d015166eaf2198c52fa9a8df7cfaeb8fdb7d46a73656e6465725f73696758405a954e35fa40b0aec27f83a8d6124b5c2f68622c5f4799bc66ff4ff994ffcad14b22dbf5a0a1438d3b812375aab16637659207e745f705f436a599a3ee2bfaac';
253+
219254
export const ParsedUnsignedTransaction = {
220255
operations: [
221256
{
@@ -347,19 +382,17 @@ export const TxnId = '4c10cf22a768a20e7eebc86e49c031d0e22895a39c6355b5f7455b2aca
347382
export const PublicNodeApiBroadcastResponse =
348383
'd9d9f7a266737461747573677265706c6965646b6365727469666963617465590317d9d9f7a2647472656583018301820458200548bee8d4a0ada144f09841a1814e0c7b06a9c525e19d07990c27a8d5dfebe983018204582059964f7dcd455bb5333f0424188250c1bafdfee505b6d4bffce6b93d84b02fbc83024e726571756573745f7374617475738301820458208ec4679d2b1049ab4154b9113c88a7bacc1772831a799d0337e650fe093339648302582086ab628166c7c823c4fac064f42bcb6c6939aec9a63ce88a2eef553475fd55958301830183024a6572726f725f636f646582034649433035303383024b72656a6563745f636f646582034105830183024e72656a6563745f6d65737361676582035901984572726f722066726f6d2043616e69737465722072796a6c332d74796161612d61616161612d61616162612d6361693a2043616e69737465722063616c6c656420606963302e74726170602077697468206d6573736167653a20746865206465626974206163636f756e7420646f65736e2774206861766520656e6f7567682066756e647320746f20636f6d706c65746520746865207472616e73616374696f6e2c2063757272656e742062616c616e63653a20302e303030303030303020546f6b656e2e0a436f6e736964657220677261636566756c6c792068616e646c696e67206661696c757265732066726f6d20746869732063616e6973746572206f7220616c746572696e67207468652063616e697374657220746f2068616e646c6520657863657074696f6e732e2053656520646f63756d656e746174696f6e3a20687474703a2f2f696e7465726e6574636f6d70757465722e6f72672f646f63732f63757272656e742f7265666572656e6365732f657865637574696f6e2d6572726f727323747261707065642d6578706c696369746c7983024673746174757382034872656a6563746564830182045820535b0b886d8f16a1d4909618e38af89fa407ef6f606c1e667ab31015f35db57f83024474696d658203498ad7d790e682f69918697369676e61747572655830a26f5ae0c1396f6005487223031062886416c7d4ea37a1b2a7b64a287b376a5f4495cffd99a69bf4f4fd95e53794f415';
349384

350-
export const SignedTransactionWithoutMemo =
351-
'b9000367636f6e74656e74b900066c726571756573745f747970656463616c6c6b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f70626361726758410a0012080a0608f0c5eadc031a0308904e2a220a20c3d30f404955975adaba89f2e1ebc75c1f44a6a204578afce8f3780d64fe252e3a0a0880a48596eb92b599186673656e646572581db32b534dcc87771406ce0d93595733ca9c635f0f2f3e29559e8806a1026e696e67726573735f6578706972791b1832d4ce93deb2006d73656e6465725f7075626b6579d84058583056301006072a8648ce3d020106052b8104000a0342000482ef63ee315d6323c616970c93267ca92ee81a691027f9c856ccd23f414f32c5209b7b6f64f42e66c9c5adf064cf0f372ae1b27c9a0fcbc4dcaa8fb5cd5ba0e66a73656e6465725f7369675840d5fa414e9308da3d900520cd48349cdb5bcdb9ec87060ad48aedc9f36356fd897c12822ee2434917e76248ae4a827a723c9ca616488e01037245df67c11e1f1d';
385+
export const RecoverySignedTransactionWithoutMemo =
386+
'b9000367636f6e74656e74b900066c726571756573745f747970656463616c6c6b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f706263617267583f12080a0608f0c5eadc031a0308904e2a220a20c3d30f404955975adaba89f2e1ebc75c1f44a6a204578afce8f3780d64fe252e3a0a0880a48596eb92b599186673656e646572581db32b534dcc87771406ce0d93595733ca9c635f0f2f3e29559e8806a1026e696e67726573735f6578706972791b1832d4ce93deb2006d73656e6465725f7075626b6579d84058583056301006072a8648ce3d020106052b8104000a0342000482ef63ee315d6323c616970c93267ca92ee81a691027f9c856ccd23f414f32c5209b7b6f64f42e66c9c5adf064cf0f372ae1b27c9a0fcbc4dcaa8fb5cd5ba0e66a73656e6465725f7369675840c9b8a7bb6d304a684423e108b0fc510d78c4e4b0aa37d66366d32f24bab48a3a1da9eeff92c77ee0aa288bea1369d6696b7d975af5e0f0f6f8b8809a4b0143db';
352387

353-
export const SignedTransactionWithMemo =
388+
export const RecoverySignedTransactionWithMemo =
354389
'b9000367636f6e74656e74b900066c726571756573745f747970656463616c6c6b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f70626361726758440a0308d20912080a0608f0c5eadc031a0308904e2a220a20c3d30f404955975adaba89f2e1ebc75c1f44a6a204578afce8f3780d64fe252e3a0a0880a48596eb92b599186673656e646572581db32b534dcc87771406ce0d93595733ca9c635f0f2f3e29559e8806a1026e696e67726573735f6578706972791b1832d4ce93deb2006d73656e6465725f7075626b6579d84058583056301006072a8648ce3d020106052b8104000a0342000482ef63ee315d6323c616970c93267ca92ee81a691027f9c856ccd23f414f32c5209b7b6f64f42e66c9c5adf064cf0f372ae1b27c9a0fcbc4dcaa8fb5cd5ba0e66a73656e6465725f7369675840819eeac2eeb59a283ab7c52a48a25a7abde85a8af02632245a3a89ace413cd2043c5bb662cf736a66c77bd61b606e581948843592f4ab8132925aff3826ba87c';
355390

356391
export const RecoverTransactionSignatureWithoutMemo = [
357392
{
358393
signing_payload: {
359-
hex_bytes: '0a69632d726571756573744638d4e2c21864b52d8edbabac4eca2b0b53ea132f5527226692aa2af17e9ed4',
360-
account_identifier: {
361-
address: '4623c8c75bf76b1275460328de94a6f1b9f9000d173941694cb93a8bd26b77ca',
362-
},
394+
hex_bytes: '0a69632d7265717565737406b1635ce592ff5a70c21936bec1148f17e40b08155d29f1e7eeb73a50b3b2b5',
395+
account_identifier: { address: '4623c8c75bf76b1275460328de94a6f1b9f9000d173941694cb93a8bd26b77ca' },
363396
signature_type: 'ecdsa',
364397
},
365398
signature_type: 'ecdsa',
@@ -368,7 +401,7 @@ export const RecoverTransactionSignatureWithoutMemo = [
368401
curve_type: 'secp256k1',
369402
},
370403
hex_bytes:
371-
'd5fa414e9308da3d900520cd48349cdb5bcdb9ec87060ad48aedc9f36356fd897c12822ee2434917e76248ae4a827a723c9ca616488e01037245df67c11e1f1d',
404+
'c9b8a7bb6d304a684423e108b0fc510d78c4e4b0aa37d66366d32f24bab48a3a1da9eeff92c77ee0aa288bea1369d6696b7d975af5e0f0f6f8b8809a4b0143db',
372405
},
373406
];
374407

0 commit comments

Comments
 (0)