Skip to content

Commit b9cf9e0

Browse files
Revert "feat(sdk-coin-icp): Added txn hash generation logic"
1 parent 37ff071 commit b9cf9e0

File tree

6 files changed

+7
-115
lines changed

6 files changed

+7
-115
lines changed

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

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,3 @@ export interface RecoveryOptions {
194194
export interface PublicNodeSubmitResponse {
195195
status: string;
196196
}
197-
198-
export interface AccountIdentifierHex {
199-
hash: Buffer<ArrayBuffer>;
200-
}

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

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ export class Transaction extends BaseTransaction {
3434
protected _signedTransaction: string;
3535
protected _signaturePayload: Signatures[];
3636
protected _createdTimestamp: number | bigint | undefined;
37-
protected _txnId: string | undefined;
3837
protected _utils: Utils;
3938

4039
constructor(_coinConfig: Readonly<CoinConfig>, utils: Utils) {
@@ -90,14 +89,6 @@ export class Transaction extends BaseTransaction {
9089
return this._createdTimestamp;
9190
}
9291

93-
set txnId(txnId: string) {
94-
this._txnId = txnId;
95-
}
96-
97-
get txnId(): string | undefined {
98-
return this._txnId;
99-
}
100-
10192
async fromRawTransaction(rawTransaction: string): Promise<void> {
10293
try {
10394
const jsonRawTransaction: RawTransaction = JSON.parse(rawTransaction);
@@ -124,7 +115,7 @@ export class Transaction extends BaseTransaction {
124115
throw new Error('Invalid transaction type');
125116
}
126117
} catch (error) {
127-
throw new InvalidTransactionError(`Invalid raw transaction: ${error.message}`);
118+
throw new InvalidTransactionError('Invalid raw transaction');
128119
}
129120
}
130121

@@ -146,7 +137,7 @@ export class Transaction extends BaseTransaction {
146137
switch (this._icpTransactionData.transactionType) {
147138
case OperationType.TRANSACTION:
148139
const txData: TxData = {
149-
id: this._id, //TODO set transaction ID
140+
id: this._id,
150141
sender: this._icpTransactionData.senderAddress,
151142
senderPublicKey: this._icpTransactionData.senderPublicKeyHex,
152143
recipient: this._icpTransactionData.receiverAddress,

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

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
1313
protected _memo: number | BigInt;
1414
protected _receiverId: string;
1515
protected _amount: string;
16-
protected _txnId: string | undefined;
1716

1817
constructor(_coinConfig: Readonly<CoinConfig>) {
1918
super(_coinConfig);
@@ -170,10 +169,5 @@ export abstract class TransactionBuilder extends BaseTransactionBuilder {
170169
this._transaction.signaturePayload
171170
);
172171
this._transaction.signedTransaction = signedTransactionBuilder.getSignTransaction();
173-
this._transaction.txnId = utils.getTransactionId(
174-
this._transaction.unsignedTransaction,
175-
this._sender,
176-
this._receiverId
177-
);
178172
}
179173
}

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

Lines changed: 5 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,15 @@ import {
1919
SendArgs,
2020
PayloadsData,
2121
CurveType,
22-
AccountIdentifierHex,
23-
CborUnsignedTransaction,
2422
} from './iface';
2523
import { KeyPair as IcpKeyPair } from './keyPair';
26-
import { decode, encode, Encoder } from 'cbor-x'; // The "cbor-x" library is used here because it supports modern features like BigInt. do not replace it with "cbor as "cbor" is not compatible with Rust's serde_cbor when handling big numbers.
24+
import { decode, encode } from 'cbor-x'; // The "cbor-x" library is used here because it supports modern features like BigInt. do not replace it with "cbor as "cbor" is not compatible with Rust's serde_cbor when handling big numbers.
2725
import js_sha256 from 'js-sha256';
2826
import BigNumber from 'bignumber.js';
2927
import { secp256k1 } from '@noble/curves/secp256k1';
3028
import protobuf from 'protobufjs';
3129
import { protoDefinition } from './protoDefinition';
3230

33-
// Create a custom encoder that avoids tagging
34-
const encoder = new Encoder({
35-
structuredClone: false,
36-
useToJSON: false,
37-
mapsAsObjects: false,
38-
largeBigIntToFloat: false,
39-
});
40-
4131
export class Utils implements BaseUtils {
4232
/** @inheritdoc */
4333
isValidSignature(signature: string): boolean {
@@ -613,18 +603,18 @@ export class Utils implements BaseUtils {
613603
return principalBytes;
614604
}
615605

616-
fromArgs(arg: Uint8Array): SendArgs {
606+
async fromArgs(arg: Uint8Array): Promise<SendArgs> {
617607
const root = protobuf.parse(protoDefinition).root;
618608
const SendRequestMessage = root.lookupType('SendRequest');
619609
const args = SendRequestMessage.decode(arg) as unknown as SendArgs;
620610
const transformedArgs: SendArgs = {
621-
payment: { receiverGets: { e8s: Number(args.payment.receiverGets.e8s) } },
622-
maxFee: { e8s: Number(args.maxFee.e8s) },
611+
payment: { receiverGets: { e8s: args.payment.receiverGets.e8s } },
612+
maxFee: { e8s: args.maxFee.e8s },
623613
to: { hash: Buffer.from(args.to.hash) },
624614
createdAtTime: { timestampNanos: BigNumber(args.createdAtTime.timestampNanos.toString()).toNumber() },
625615
};
626616
if (args.memo !== undefined && args.memo !== null) {
627-
transformedArgs.memo = { memo: Number(args.memo?.memo?.toString()) };
617+
transformedArgs.memo = { memo: BigInt(args.memo?.memo?.toString()) };
628618
}
629619
return transformedArgs;
630620
}
@@ -683,81 +673,6 @@ export class Utils implements BaseUtils {
683673
const s = Buffer.from(signature.s.toString(16).padStart(64, '0'), 'hex');
684674
return Buffer.concat([r, s]).toString('hex');
685675
};
686-
687-
getTransactionId(encodedUnsignedTransaction: string, sender: string, receiver: string): string {
688-
const unsignedTransaction = utils.cborDecode(
689-
utils.blobFromHex(encodedUnsignedTransaction)
690-
) as CborUnsignedTransaction;
691-
for (const [, update] of unsignedTransaction.updates as unknown as [string, HttpCanisterUpdate][]) {
692-
const args = update.arg;
693-
const sendArgs = utils.fromArgs(args);
694-
const hash = this.generateTransactionHash(sendArgs, sender, receiver);
695-
return hash;
696-
}
697-
throw new Error('Unable to compute transaction ID: no updates found in the unsigned transaction.');
698-
}
699-
700-
safeBigInt(val: unknown): number | bigint {
701-
if (typeof val === 'bigint') return val;
702-
if (typeof val !== 'number') throw new Error('Expected number or bigint');
703-
704-
if (val > Number.MAX_SAFE_INTEGER || val < Number.MIN_SAFE_INTEGER) {
705-
return BigInt(val);
706-
}
707-
return val;
708-
}
709-
710-
generateTransactionHash(sendArgs: SendArgs, sender: string, receiver: string): string {
711-
const from = this.accountIdentifier(sender);
712-
const to = this.accountIdentifier(receiver);
713-
714-
const transferMap = new Map<any, any>([
715-
[0, from],
716-
[1, to],
717-
[2, new Map([[0, this.safeBigInt(Number(sendArgs.payment.receiverGets.e8s))]])],
718-
[3, new Map([[0, sendArgs.maxFee.e8s]])],
719-
]);
720-
721-
const operationMap = new Map([[2, transferMap]]);
722-
const txnMap = new Map<any, any>([
723-
[0, operationMap],
724-
[1, this.safeBigInt(sendArgs.memo?.memo ?? 0)], //TODO need to make memo as optional, ticket: WIN-5209
725-
[2, new Map([[0, BigInt(sendArgs.createdAtTime.timestampNanos)]])],
726-
]);
727-
728-
const transactionMap = this.getProcessedTransactionMap(txnMap);
729-
const serializedTxn = encoder.encode(transactionMap);
730-
return crypto.createHash('sha256').update(serializedTxn).digest('hex');
731-
}
732-
733-
accountIdentifier(hexStr: string): AccountIdentifierHex {
734-
const bytes = Buffer.from(hexStr, 'hex');
735-
if (bytes.length === 28) {
736-
return { hash: bytes };
737-
}
738-
if (bytes.length === 32) {
739-
return { hash: bytes.slice(4) };
740-
}
741-
throw new Error(`Invalid AccountIdentifier: expected 56 or 64 hex chars, got ${hexStr.length}`);
742-
}
743-
744-
getProcessedTransactionMap(txn: Map<any, any>): Map<any, any> {
745-
const operationMap = txn.get(0);
746-
const transferMap = operationMap.get(2);
747-
transferMap.set(0, this.serializeAccountIdentifier(transferMap.get(0)));
748-
transferMap.set(1, this.serializeAccountIdentifier(transferMap.get(1)));
749-
return txn;
750-
}
751-
752-
serializeAccountIdentifier(accountHex: AccountIdentifierHex): string {
753-
if (accountHex && accountHex.hash) {
754-
const hash = accountHex.hash;
755-
const checksum = Buffer.alloc(4);
756-
checksum.writeUInt32BE(crc32.buf(hash) >>> 0, 0);
757-
return Buffer.concat([checksum, hash]).toString('hex').toLowerCase();
758-
}
759-
throw new Error('Invalid accountHex format');
760-
}
761676
}
762677

763678
const utils = new Utils();

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,6 @@ export const payloadsData = {
195195
'b90002677570646174657381826b5452414e53414354494f4eb900056b63616e69737465725f69644a000000000000000201016b6d6574686f645f6e616d656773656e645f70626361726758400a0308d20912040a02080a1a0308904e2a220a20c3d30f404955975adaba89f2e1ebc75c1f44a6a204578afce8f3780d64fe252e3a0a0880a48596eb92b599186673656e646572581dd5fc1dc4d74d4aa35d81cf345533d20548113412d32fffdcece2f68a026e696e67726573735f6578706972791b000000000000000070696e67726573735f6578706972696573811b1832d4ce93deb200',
196196
};
197197

198-
export const transactionHash = '87f2e7ca80961bdc3a1fe761553a8a7f8ac5bf28b71f4e1fba807cf352a27f52';
199-
200198
export const payloadsDataWithoutMemo = {
201199
payloads: [
202200
{

modules/sdk-coin-icp/test/unit/transactionBuilder/transactionBuilder.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,6 @@ describe('ICP Transaction Builder', async () => {
9292
const signedTxn = txBuilder.transaction.signedTransaction;
9393
signedTxn.should.be.a.String();
9494
should.equal(signedTxn, testData.SignedTransaction);
95-
const transactionHash = txBuilder.transaction.txnId;
96-
should.equal(transactionHash, testData.transactionHash);
9795
const broadcastTxn = txBuilder.transaction.toBroadcastFormat();
9896
broadcastTxn.should.be.a.String();
9997
should.equal(broadcastTxn, signedTxn);

0 commit comments

Comments
 (0)