diff --git a/packages/ledger/src/converters/ledger.converters.ts b/packages/ledger/src/converters/ledger.converters.ts index eb4f0bc2..1d5282ed 100644 --- a/packages/ledger/src/converters/ledger.converters.ts +++ b/packages/ledger/src/converters/ledger.converters.ts @@ -10,6 +10,11 @@ import type { TransferParams, } from "../types/ledger.params"; +// WARNING: When using the ICRC-1 interface of the ICP ledger, there is no +// relationship between the memo and the icrc1Memo of a transaction. The ICRC-1 +// interface simply cannot set the memo field and the non-ICRC-1 interface +// cannot set the icrc1Memo field, even though the icrc1Memo field is called +// just "memo" in canister method params. export const toTransferArg = ({ from_subaccount, fee, diff --git a/packages/ledger/src/types/ledger.params.ts b/packages/ledger/src/types/ledger.params.ts index 095624a8..7f4e4566 100644 --- a/packages/ledger/src/types/ledger.params.ts +++ b/packages/ledger/src/types/ledger.params.ts @@ -13,6 +13,11 @@ import type { IcrcAccount } from "./ledger.responses"; */ export type BalanceParams = IcrcAccount & QueryParams; +// WARNING: When using the ICRC-1 interface of the ICP ledger, there is no +// relationship between the memo and the icrc1Memo of a transaction. The ICRC-1 +// interface simply cannot set the memo field and the non-ICRC-1 interface +// cannot set the icrc1Memo field, even though the icrc1Memo field is called +// just "memo" in canister method params. /** * Params to make a transfer in an ICRC-1 ledger * diff --git a/packages/nns/README.md b/packages/nns/README.md index 9ed66f4f..2c20eb80 100644 --- a/packages/nns/README.md +++ b/packages/nns/README.md @@ -320,7 +320,7 @@ Returns the index of the block containing the tx if it was successful. | --------------- | ---------------------------------------------------- | | `icrc1Transfer` | `(request: Icrc1TransferRequest) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/ledger.canister.ts#L137) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/ledger.canister.ts#L142) ### :factory: GovernanceCanister @@ -453,7 +453,7 @@ Increases dissolve delay of a neuron | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | `increaseDissolveDelay` | `({ neuronId, additionalDissolveDelaySeconds, }: { neuronId: bigint; additionalDissolveDelaySeconds: number; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L371) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L373) ##### :gear: setDissolveDelay @@ -464,7 +464,7 @@ The new date is now + dissolveDelaySeconds. | ------------------ | ------------------------------------------------------------------------------------------------------------- | | `setDissolveDelay` | `({ neuronId, dissolveDelaySeconds, }: { neuronId: bigint; dissolveDelaySeconds: number; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L403) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L405) ##### :gear: startDissolving @@ -474,7 +474,7 @@ Start dissolving process of a neuron | ----------------- | ------------------------------------- | | `startDissolving` | `(neuronId: bigint) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L426) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L428) ##### :gear: stopDissolving @@ -484,7 +484,7 @@ Stop dissolving process of a neuron | ---------------- | ------------------------------------- | | `stopDissolving` | `(neuronId: bigint) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L443) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L445) ##### :gear: joinCommunityFund @@ -494,7 +494,7 @@ Neuron joins the community fund | ------------------- | ------------------------------------- | | `joinCommunityFund` | `(neuronId: bigint) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L460) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L462) ##### :gear: autoStakeMaturity @@ -509,7 +509,7 @@ Parameters: - `neuronId`: The id of the neuron for which to request a change of the auto stake feature - `autoStake`: `true` to enable the auto-stake maturity for this neuron, `false` to turn it off -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L482) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L484) ##### :gear: leaveCommunityFund @@ -519,7 +519,7 @@ Neuron leaves the community fund | -------------------- | ------------------------------------- | | `leaveCommunityFund` | `(neuronId: bigint) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L496) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L498) ##### :gear: setNodeProviderAccount @@ -530,7 +530,7 @@ Where the reward is paid to. | ------------------------ | ---------------------------------------------- | | `setNodeProviderAccount` | `(accountIdentifier: string) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L513) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L515) ##### :gear: mergeNeurons @@ -540,7 +540,7 @@ Merge two neurons | -------------- | --------------------------------------------------------------------------------- | | `mergeNeurons` | `(request: { sourceNeuronId: bigint; targetNeuronId: bigint; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L533) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L535) ##### :gear: simulateMergeNeurons @@ -550,7 +550,7 @@ Simulate merging two neurons | ---------------------- | --------------------------------------------------------------------------------------- | | `simulateMergeNeurons` | `(request: { sourceNeuronId: bigint; targetNeuronId: bigint; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L550) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L552) ##### :gear: splitNeuron @@ -560,7 +560,7 @@ Splits a neuron creating a new one | ------------- | ----------------------------------------------------------------------------------- | | `splitNeuron` | `({ neuronId, amount, }: { neuronId: bigint; amount: bigint; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L595) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L597) ##### :gear: getProposal @@ -573,7 +573,7 @@ it is fetched using a query call. | ------------- | ----------------------------------------------------------------------------------------------------- | | `getProposal` | `({ proposalId, certified, }: { proposalId: bigint; certified?: boolean; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L635) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L637) ##### :gear: makeProposal @@ -583,7 +583,7 @@ Create new proposal | -------------- | ------------------------------------------------- | | `makeProposal` | `(request: MakeProposalRequest) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L652) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L654) ##### :gear: registerVote @@ -593,7 +593,7 @@ Registers vote for a proposal from the neuron passed. | -------------- | ----------------------------------------------------------------------------------------------------------- | | `registerVote` | `({ neuronId, vote, proposalId, }: { neuronId: bigint; vote: Vote; proposalId: bigint; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L667) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L669) ##### :gear: setFollowees @@ -603,7 +603,7 @@ Edit neuron followees per topic | -------------- | ------------------------------------------------- | | `setFollowees` | `(followRequest: FollowRequest) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L689) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L691) ##### :gear: disburse @@ -613,7 +613,7 @@ Disburse neuron on Account | ---------- | --------------------------------------------------------------------------------------------------------------------- | | `disburse` | `({ neuronId, toAccountId, amount, }: { neuronId: bigint; toAccountId?: string; amount?: bigint; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L704) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L706) ##### :gear: mergeMaturity @@ -623,7 +623,7 @@ Merge Maturity of a neuron | --------------- | ------------------------------------------------------------------------------------------------------- | | `mergeMaturity` | `({ neuronId, percentageToMerge, }: { neuronId: bigint; percentageToMerge: number; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L743) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L745) ##### :gear: stakeMaturity @@ -638,7 +638,7 @@ Parameters: - `neuronId`: The id of the neuron for which to stake the maturity - `percentageToStake`: Optional. Percentage of the current maturity to stake. If not provided, all of the neuron's current maturity will be staked. -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L776) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L778) ##### :gear: spawnNeuron @@ -648,7 +648,7 @@ Merge Maturity of a neuron | ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `spawnNeuron` | `({ neuronId, percentageToSpawn, newController, nonce, }: { neuronId: bigint; percentageToSpawn?: number; newController?: Principal; nonce?: bigint; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L798) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L800) ##### :gear: addHotkey @@ -658,7 +658,7 @@ Add hotkey to neuron | ----------- | ------------------------------------------------------------------------------------------ | | `addHotkey` | `({ neuronId, principal, }: { neuronId: bigint; principal: Principal; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L852) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L854) ##### :gear: removeHotkey @@ -668,7 +668,7 @@ Remove hotkey to neuron | -------------- | ------------------------------------------------------------------------------------------ | | `removeHotkey` | `({ neuronId, principal, }: { neuronId: bigint; principal: Principal; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L876) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L878) ##### :gear: claimOrRefreshNeuronFromAccount @@ -678,7 +678,7 @@ Gets the NeuronID of a newly created neuron. | --------------------------------- | --------------------------------------------------------------------------------------- | | `claimOrRefreshNeuronFromAccount` | `({ memo, controller, }: { memo: bigint; controller?: Principal; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L897) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L899) ##### :gear: claimOrRefreshNeuron @@ -689,7 +689,7 @@ Uses query call only. | ---------------------- | ----------------------------------------------------------- | | `claimOrRefreshNeuron` | `(request: ClaimOrRefreshNeuronRequest) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L928) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L930) ##### :gear: getNeuron @@ -699,7 +699,7 @@ Return the data of the neuron provided as id. | ----------- | ---------------------------------------------------------------------------------------------- | | `getNeuron` | `({ certified, neuronId, }: { certified: boolean; neuronId: bigint; }) => Promise` | -[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L979) +[:link: Source](https://github.com/dfinity/ic-js/tree/main/packages/nns/src/governance.canister.ts#L981) ### :factory: ICP diff --git a/packages/nns/src/canisters/ledger/ledger.request.converts.ts b/packages/nns/src/canisters/ledger/ledger.request.converts.ts index c50c60b0..e1bde1c0 100644 --- a/packages/nns/src/canisters/ledger/ledger.request.converts.ts +++ b/packages/nns/src/canisters/ledger/ledger.request.converts.ts @@ -52,18 +52,23 @@ export const toTransferRawRequest = ({ : [arrayOfNumberToUint8Array(fromSubAccount)], }); +// WARNING: When using the ICRC-1 interface of the ICP ledger, there is no +// relationship between the memo and the icrc1Memo of a transaction. The ICRC-1 +// interface simply cannot set the memo field and the non-ICRC-1 interface +// cannot set the icrc1Memo field, even though the icrc1Memo field is called +// just "memo" in canister method params. export const toIcrc1TransferRawRequest = ({ fromSubAccount, to, amount, fee, - memo, + icrc1Memo, createdAt, }: Icrc1TransferRequest): Icrc1TransferRawRequest => ({ to, fee: toNullable(fee ?? TRANSACTION_FEE), amount, - memo: toNullable(memo), + memo: toNullable(icrc1Memo), created_at_time: toNullable(createdAt), from_subaccount: toNullable(fromSubAccount), }); diff --git a/packages/nns/src/governance.canister.ts b/packages/nns/src/governance.canister.ts index f6d7408a..7ba52a01 100644 --- a/packages/nns/src/governance.canister.ts +++ b/packages/nns/src/governance.canister.ts @@ -335,7 +335,9 @@ export class GovernanceCanister { // Send amount to the ledger. await ledgerCanister.icrc1Transfer({ - memo: nonceBytes, + // WARNING: This does not set the same memo field as the stakeNeuron + // function above and would need to be handled separately from that field. + icrc1Memo: nonceBytes, amount: stake, fromSubAccount, to: { diff --git a/packages/nns/src/ledger.canister.spec.ts b/packages/nns/src/ledger.canister.spec.ts index 65bb98fd..79ad5e3e 100644 --- a/packages/nns/src/ledger.canister.spec.ts +++ b/packages/nns/src/ledger.canister.spec.ts @@ -651,7 +651,7 @@ describe("LedgerCanister", () => { Ok: BigInt(1234), }); const fee = BigInt(10_000); - const memo = new Uint8Array([3, 4, 5, 6]); + const icrc1Memo = new Uint8Array([3, 4, 5, 6]); const ledger = LedgerCanister.create({ certifiedServiceOverride: service, }); @@ -659,14 +659,14 @@ describe("LedgerCanister", () => { to, amount, fee, - memo, + icrc1Memo, }); expect(service.icrc1_transfer).toBeCalledWith({ to, fee: [fee], amount, - memo: [memo], + memo: [icrc1Memo], created_at_time: [], from_subaccount: [], }); @@ -703,7 +703,7 @@ describe("LedgerCanister", () => { Ok: BigInt(1234), }); const fee = BigInt(10_000); - const memo = new Uint8Array([3, 4, 5, 6]); + const icrc1Memo = new Uint8Array([3, 4, 5, 6]); const ledger = LedgerCanister.create({ certifiedServiceOverride: service, }); @@ -712,7 +712,7 @@ describe("LedgerCanister", () => { to, amount, fee, - memo, + icrc1Memo, createdAt, }); @@ -720,7 +720,7 @@ describe("LedgerCanister", () => { to, fee: [fee], amount, - memo: [memo], + memo: [icrc1Memo], created_at_time: [createdAt], from_subaccount: [], }); @@ -732,7 +732,7 @@ describe("LedgerCanister", () => { Ok: BigInt(1234), }); const fee = BigInt(10_000); - const memo = new Uint8Array(); + const icrc1Memo = new Uint8Array(); const fromSubAccount = new Uint8Array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, @@ -744,7 +744,7 @@ describe("LedgerCanister", () => { to, amount, fee, - memo, + icrc1Memo, fromSubAccount, }); @@ -752,7 +752,7 @@ describe("LedgerCanister", () => { to, fee: [fee], amount, - memo: [memo], + memo: [icrc1Memo], created_at_time: [], from_subaccount: [fromSubAccount], }); @@ -764,7 +764,7 @@ describe("LedgerCanister", () => { Ok: BigInt(1234), }); const fee = BigInt(10_000); - const memo = new Uint8Array(); + const icrc1Memo = new Uint8Array(); const toSubAccount = new Uint8Array([ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, @@ -779,7 +779,7 @@ describe("LedgerCanister", () => { }, amount, fee, - memo, + icrc1Memo, }); expect(service.icrc1_transfer).toBeCalledWith({ @@ -789,7 +789,7 @@ describe("LedgerCanister", () => { }, fee: [fee], amount, - memo: [memo], + memo: [icrc1Memo], created_at_time: [], from_subaccount: [], }); @@ -925,11 +925,11 @@ describe("LedgerCanister", () => { hardwareWallet: true, }); - const memo = new Uint8Array(); + const icrc1Memo = new Uint8Array(); await ledger.icrc1Transfer({ to, amount, - memo, + icrc1Memo, }); expect(service.transfer_fee).not.toBeCalled(); @@ -938,7 +938,7 @@ describe("LedgerCanister", () => { to, fee: [BigInt(10000)], amount, - memo: [memo], + memo: [icrc1Memo], created_at_time: [], from_subaccount: [], }); @@ -956,12 +956,12 @@ describe("LedgerCanister", () => { }); const fee = BigInt(990_000); - const memo = new Uint8Array(); + const icrc1Memo = new Uint8Array(); await ledger.icrc1Transfer({ to, amount, fee, - memo, + icrc1Memo, }); expect(service.transfer_fee).not.toBeCalled(); @@ -970,7 +970,7 @@ describe("LedgerCanister", () => { to, fee: [fee], amount, - memo: [memo], + memo: [icrc1Memo], created_at_time: [], from_subaccount: [], }); diff --git a/packages/nns/src/ledger.canister.ts b/packages/nns/src/ledger.canister.ts index 095352d9..6a9f3e75 100644 --- a/packages/nns/src/ledger.canister.ts +++ b/packages/nns/src/ledger.canister.ts @@ -128,6 +128,11 @@ export class LedgerCanister { return response.Ok; }; + // WARNING: When using the ICRC-1 interface of the ICP ledger, there is no + // relationship between the memo and the icrc1Memo of a transaction. The + // ICRC-1 interface simply cannot set the memo field and the non-ICRC-1 + // interface cannot set the icrc1Memo field, even though the icrc1Memo field + // is called just "memo" in canister method params. /** * Transfer ICP from the caller to the destination `Account`. * Returns the index of the block containing the tx if it was successful. diff --git a/packages/nns/src/types/ledger_converters.ts b/packages/nns/src/types/ledger_converters.ts index 901f080f..ade1ade7 100644 --- a/packages/nns/src/types/ledger_converters.ts +++ b/packages/nns/src/types/ledger_converters.ts @@ -20,10 +20,15 @@ export type TransferRequest = { createdAt?: bigint; }; +// WARNING: When using the ICRC-1 interface of the ICP ledger, there is no +// relationship between the memo and the icrc1Memo of a transaction. The ICRC-1 +// interface simply cannot set the memo field and the non-ICRC-1 interface +// cannot set the icrc1Memo field, even though the icrc1Memo field is called +// just "memo" in canister method params. export type Icrc1TransferRequest = { to: Account; amount: Icrc1Tokens; - memo?: Uint8Array; + icrc1Memo?: Uint8Array; fee?: Icrc1Tokens; fromSubAccount?: SubAccount; // Nanoseconds since unix epoc to trigger deduplication and avoid other issues diff --git a/scripts/build-next b/scripts/build-next index 3dee425a..98b0204f 100755 --- a/scripts/build-next +++ b/scripts/build-next @@ -7,7 +7,8 @@ npm ci node ./scripts/update-version.mjs utils node ./scripts/update-version.mjs nns-proto node ./scripts/update-version.mjs ledger -node ./scripts/update-version.mjs ledger-icp +# TODO: uncomment when new @dfinity/ledger-icp will be released +# node ./scripts/update-version.mjs ledger-icp node ./scripts/update-version.mjs nns node ./scripts/update-version.mjs sns node ./scripts/update-version.mjs cmc