Skip to content

Commit cab3bcc

Browse files
committed
feat(sdk-coin-icp): implemented default memo as 0 and related changes
TICKET: WIN-5232
1 parent 967cef6 commit cab3bcc

File tree

11 files changed

+184
-295
lines changed

11 files changed

+184
-295
lines changed

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

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export const LEDGER_CANISTER_ID = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 2, 1, 1])
99
export const ROOT_PATH = 'm/0';
1010
export const ACCOUNT_BALANCE_ENDPOINT = '/account/balance';
1111
export const PUBLIC_NODE_REQUEST_ENDPOINT = '/api/v3/canister/';
12+
export const DEFAULT_MEMO = 0; // default memo value is 0
1213

1314
export enum RequestType {
1415
CALL = 'call',
@@ -41,7 +42,7 @@ export interface IcpTransactionData {
4142
amount: string;
4243
fee: string;
4344
senderPublicKeyHex: string;
44-
memo?: number | BigInt; // memo in string is not accepted by ICP chain.
45+
memo: number | BigInt; // memo in string is not accepted by ICP chain.
4546
transactionType: OperationType;
4647
expiryTime: number | BigInt;
4748
}
@@ -71,38 +72,31 @@ export interface IcpOperation {
7172
amount: IcpAmount;
7273
}
7374

74-
export interface IcpTransactionParseMetadata {
75+
export interface MetaData {
7576
created_at_time: number;
76-
memo?: number | BigInt; // memo in string is not accepted by ICP chain.
77+
memo: number | BigInt; // memo in string is not accepted by ICP chain.
7778
ingress_start?: number | BigInt; // it should be nano seconds
7879
ingress_end?: number | BigInt; // it should be nano seconds
7980
}
8081

81-
export interface IcpTransactionBuildMetadata {
82-
created_at_time: number;
83-
memo?: number | BigInt; // memo in string is not accepted by ICP chain.
84-
ingress_start: number | BigInt; // it should be nano seconds
85-
ingress_end: number | BigInt; // it should be nano seconds
86-
}
87-
8882
export interface IcpTransaction {
8983
public_keys: IcpPublicKey[];
9084
operations: IcpOperation[];
91-
metadata: IcpTransactionBuildMetadata;
85+
metadata: MetaData;
9286
}
9387

9488
export interface ParsedTransaction {
9589
operations: IcpOperation[];
9690
account_identifier_signers: IcpAccount[];
97-
metadata: IcpTransactionParseMetadata;
91+
metadata: MetaData;
9892
}
9993

10094
export interface IcpAccountIdentifier {
10195
address: string;
10296
}
10397

10498
export interface SendArgs {
105-
memo?: { memo: number | BigInt };
99+
memo: { memo: number | BigInt };
106100
payment: { receiverGets: { e8s: number } };
107101
maxFee: { e8s: number };
108102
to: { hash: Buffer };

modules/sdk-coin-icp/src/lib/staticProtoDefinition.json

Lines changed: 0 additions & 92 deletions
This file was deleted.

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

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,9 @@ export class Transaction extends BaseTransaction {
109109
senderPublicKeyHex: senderPublicKeyHex,
110110
transactionType: transactionType,
111111
expiryTime: Number(parsedTx.metadata.created_at_time + (MAX_INGRESS_TTL - PERMITTED_DRIFT)),
112+
memo: parsedTx.metadata.memo,
112113
};
113-
if (parsedTx.metadata.memo !== undefined) {
114-
this._icpTransactionData.memo = parsedTx.metadata.memo;
115-
}
114+
116115
this._utils.validateRawTransaction(this._icpTransactionData);
117116
this._id = this.generateTransactionId();
118117
break;
@@ -284,12 +283,10 @@ export class Transaction extends BaseTransaction {
284283
operations: [senderOperation, receiverOperation, feeOperation],
285284
metadata: {
286285
created_at_time: args.createdAtTime.timestampNanos,
286+
memo: Number(args.memo.memo),
287287
},
288288
account_identifier_signers: accountIdentifierSigners,
289289
};
290-
if (args.memo !== undefined) {
291-
parsedTxn.metadata.memo = Number(args.memo.memo);
292-
}
293290
this.createdTimestamp = args.createdAtTime.timestampNanos;
294291
return parsedTxn;
295292
}

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import BigNumber from 'bignumber.js';
33
import { BaseTransactionBuilder, BuildTransactionError, BaseAddress, SigningError, BaseKey } from '@bitgo/sdk-core';
44
import { Transaction } from './transaction';
55
import utils from './utils';
6-
import { IcpTransaction, IcpTransactionData, PayloadsData, Signatures } from './iface';
6+
import { DEFAULT_MEMO, IcpTransaction, IcpTransactionData, PayloadsData, Signatures } from './iface';
77
import { SignedTransactionBuilder } from './signedTransactionBuilder';
88

99
export abstract class TransactionBuilder extends BaseTransactionBuilder {
@@ -137,9 +137,7 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
137137
this._receiverId = icpTransactionData.receiverAddress;
138138
this._publicKey = icpTransactionData.senderPublicKeyHex;
139139
this._amount = icpTransactionData.amount;
140-
if (icpTransactionData.memo !== undefined) {
141-
this._memo = icpTransactionData.memo;
142-
}
140+
this._memo = icpTransactionData.memo ?? DEFAULT_MEMO;
143141
}
144142

145143
validateAddress(address: BaseAddress): void {

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@ import { Transaction } from './transaction';
66
import { UnsignedTransactionBuilder } from './unsignedTransactionBuilder';
77
import {
88
CurveType,
9-
IcpTransactionBuildMetadata,
109
IcpOperation,
1110
IcpPublicKey,
1211
IcpTransaction,
1312
IcpTransactionData,
1413
OperationType,
14+
DEFAULT_MEMO,
1515
} from './iface';
1616
import assert from 'assert';
1717

@@ -34,6 +34,11 @@ export class TransferBuilder extends TransactionBuilder {
3434

3535
/** @inheritdoc */
3636
protected async buildImplementation(): Promise<Transaction> {
37+
// The ICP chain sets a memo field with a default value of 0. This ensures compatibility
38+
// by setting the memo to 0 if it's not explicitly provided.
39+
if (!this._memo || this._memo === undefined || this._memo === null) {
40+
this._memo = DEFAULT_MEMO;
41+
}
3742
this.validateTransaction(this._transaction);
3843
this.buildIcpTransactionData();
3944
const unsignedTransactionBuilder = new UnsignedTransactionBuilder(this._transaction.icpTransaction);
@@ -90,8 +95,7 @@ export class TransferBuilder extends TransactionBuilder {
9095
};
9196

9297
const createdTimestamp = this._transaction.createdTimestamp;
93-
const { metaData, ingressEndTime }: { metaData: IcpTransactionBuildMetadata; ingressEndTime: number | BigInt } =
94-
this._utils.getMetaData(this._memo, createdTimestamp);
98+
const { metaData, ingressEndTime } = this._utils.getMetaData(this._memo, createdTimestamp);
9599

96100
const icpTransaction: IcpTransaction = {
97101
public_keys: [publicKey],
@@ -106,10 +110,9 @@ export class TransferBuilder extends TransactionBuilder {
106110
senderPublicKeyHex: this._publicKey,
107111
transactionType: OperationType.TRANSACTION,
108112
expiryTime: ingressEndTime,
113+
memo: this._memo,
109114
};
110-
if (this._memo !== undefined) {
111-
icpTransactionData.memo = this._memo;
112-
}
115+
113116
this._transaction.icpTransactionData = icpTransactionData;
114117
this._transaction.icpTransaction = icpTransaction;
115118
}

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

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ export class UnsignedTransactionBuilder {
2525
Number(this._icpTransactionPayload.metadata.ingress_end) -
2626
Number(this._icpTransactionPayload.metadata.ingress_start); // 300s in nanoseconds
2727
const ingressExpiries = this.getIngressExpiries(
28-
this._icpTransactionPayload.metadata.ingress_start,
29-
this._icpTransactionPayload.metadata.ingress_end,
28+
this._icpTransactionPayload.metadata.ingress_start!,
29+
this._icpTransactionPayload.metadata.ingress_end!,
3030
interval
3131
);
3232
const sendArgs = this.getSendArgs(
33-
this._icpTransactionPayload.metadata.memo!,
33+
this._icpTransactionPayload.metadata.memo,
3434
this._icpTransactionPayload.metadata.created_at_time,
3535
this._icpTransactionPayload.operations[1].amount.value,
3636
this._icpTransactionPayload.operations[2].amount.value,
@@ -89,22 +89,15 @@ export class UnsignedTransactionBuilder {
8989
return ingressExpiries;
9090
}
9191

92-
getSendArgs(
93-
memo: number | BigInt | undefined,
94-
created_at_time: number,
95-
amount: string,
96-
fee: string,
97-
receiver: string
98-
): SendArgs {
92+
getSendArgs(memo: number | BigInt, created_at_time: number, amount: string, fee: string, receiver: string): SendArgs {
9993
const sendArgs: SendArgs = {
10094
payment: { receiverGets: { e8s: Number(amount) } },
10195
maxFee: { e8s: -Number(fee) },
10296
to: { hash: Buffer.from(receiver, 'hex') },
10397
createdAtTime: { timestampNanos: Number(created_at_time) },
98+
memo: { memo: memo },
10499
};
105-
if (memo !== undefined) {
106-
sendArgs.memo = { memo: memo };
107-
}
100+
108101
return sendArgs;
109102
}
110103

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

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import {
1515
IcpTransactionData,
1616
RequestType,
1717
Signatures,
18-
IcpTransactionBuildMetadata,
18+
MetaData,
1919
SendArgs,
2020
PayloadsData,
2121
CurveType,
@@ -367,9 +367,7 @@ export class Utils implements BaseUtils {
367367
}
368368
this.validateFee(transactionData.fee);
369369
this.validateValue(new BigNumber(transactionData.amount));
370-
if (transactionData.memo !== undefined) {
371-
this.validateMemo(transactionData.memo);
372-
}
370+
this.validateMemo(transactionData.memo);
373371
this.validateExpireTime(transactionData.expiryTime);
374372
}
375373

@@ -584,21 +582,20 @@ export class Utils implements BaseUtils {
584582
getMetaData(
585583
memo: number | BigInt,
586584
timestamp: number | bigint | undefined
587-
): { metaData: IcpTransactionBuildMetadata; ingressEndTime: number | BigInt } {
585+
): { metaData: MetaData; ingressEndTime: number | BigInt } {
588586
let currentTime = Date.now() * 1000000;
589587
if (timestamp) {
590588
currentTime = Number(timestamp);
591589
}
592590
const ingressStartTime = currentTime;
593591
const ingressEndTime = ingressStartTime + 5 * 60 * 1000000000; // 5 mins in nanoseconds
594-
const metaData: IcpTransactionBuildMetadata = {
592+
const metaData: MetaData = {
595593
created_at_time: currentTime,
596594
ingress_start: ingressStartTime,
597595
ingress_end: ingressEndTime,
596+
memo: memo,
598597
};
599-
if (memo !== undefined || !isNaN(memo)) {
600-
metaData.memo = memo;
601-
}
598+
602599
return { metaData, ingressEndTime };
603600
}
604601

@@ -620,10 +617,8 @@ export class Utils implements BaseUtils {
620617
maxFee: { e8s: Number(args.maxFee.e8s) },
621618
to: { hash: Buffer.from(args.to.hash) },
622619
createdAtTime: { timestampNanos: BigNumber(args.createdAtTime.timestampNanos.toString()).toNumber() },
620+
memo: { memo: Number(args.memo.memo.toString()) },
623621
};
624-
if (args.memo !== undefined && args.memo !== null) {
625-
transformedArgs.memo = { memo: Number(args.memo?.memo?.toString()) };
626-
}
627622
return transformedArgs;
628623
}
629624

@@ -724,7 +719,7 @@ export class Utils implements BaseUtils {
724719
const operationMap = new Map([[2, transferFields]]);
725720
const txnFields = new Map<any, any>([
726721
[0, operationMap],
727-
[1, this.safeBigInt(sendArgs.memo?.memo || 0)], // TODO: remove 0 value as memo will always be set, WIN-5232
722+
[1, this.safeBigInt(sendArgs.memo.memo)],
728723
[2, new Map([[0, BigInt(sendArgs.createdAtTime.timestampNanos)]])],
729724
]);
730725

0 commit comments

Comments
 (0)