@ledgerhq/coin-casper 3.1.0 → 3.2.0-nightly.20260901020738
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/jest.config.js +6 -1
- package/lib/api/index.d.ts +26 -3
- package/lib/api/index.d.ts.map +1 -1
- package/lib/api/index.js +10 -28
- package/lib/api/index.js.map +1 -1
- package/lib/logic/craftTransaction.d.ts.map +1 -1
- package/lib/logic/craftTransaction.js +1 -2
- package/lib/logic/craftTransaction.js.map +1 -1
- package/lib/logic/utils.d.ts +2 -0
- package/lib/logic/utils.d.ts.map +1 -1
- package/lib/logic/utils.js +11 -0
- package/lib/logic/utils.js.map +1 -1
- package/lib/logic/validateIntent.d.ts.map +1 -1
- package/lib/logic/validateIntent.js +2 -2
- package/lib/logic/validateIntent.js.map +1 -1
- package/lib/types/coinframework.d.ts +5 -1
- package/lib/types/coinframework.d.ts.map +1 -1
- package/lib-es/api/index.d.ts +26 -3
- package/lib-es/api/index.d.ts.map +1 -1
- package/lib-es/api/index.js +10 -28
- package/lib-es/api/index.js.map +1 -1
- package/lib-es/logic/craftTransaction.d.ts.map +1 -1
- package/lib-es/logic/craftTransaction.js +2 -3
- package/lib-es/logic/craftTransaction.js.map +1 -1
- package/lib-es/logic/utils.d.ts +2 -0
- package/lib-es/logic/utils.d.ts.map +1 -1
- package/lib-es/logic/utils.js +10 -0
- package/lib-es/logic/utils.js.map +1 -1
- package/lib-es/logic/validateIntent.d.ts.map +1 -1
- package/lib-es/logic/validateIntent.js +2 -2
- package/lib-es/logic/validateIntent.js.map +1 -1
- package/lib-es/types/coinframework.d.ts +5 -1
- package/lib-es/types/coinframework.d.ts.map +1 -1
- package/package.json +7 -6
- package/src/api/index.integ.test.ts +2 -1
- package/src/api/index.test.ts +28 -17
- package/src/api/index.ts +16 -60
- package/src/logic/craftTransaction.test.ts +18 -0
- package/src/logic/craftTransaction.ts +4 -3
- package/src/logic/utils.test.ts +21 -0
- package/src/logic/utils.ts +9 -0
- package/src/logic/validateIntent.test.ts +26 -0
- package/src/logic/validateIntent.ts +2 -2
- package/src/types/coinframework.ts +7 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,41 @@
|
|
|
1
1
|
# @ledgerhq/coin-casper
|
|
2
2
|
|
|
3
|
+
## 3.2.0-nightly.20260901020738
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#21190](https://github.com/LedgerHQ/ledger-live/pull/21190) [`aafcdb7`](https://github.com/LedgerHQ/ledger-live/commit/aafcdb70e59584d6580f080cfd167cce41e56c19) Thanks [@vtaranushenko-ext-ledger](https://github.com/vtaranushenko-ext-ledger)! - Preserve transferId through the generic adapter for Casper
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- [#21168](https://github.com/LedgerHQ/ledger-live/pull/21168) [`a4f727d`](https://github.com/LedgerHQ/ledger-live/commit/a4f727d0c17d685302cf9ec2a39e752b2c9937fd) Thanks [@cted-ledger](https://github.com/cted-ledger)! - Adopt the coin-module authoring type, dropping the hand-written "not supported" stubs.
|
|
12
|
+
|
|
13
|
+
`createApi` now returns its object with `satisfies CoinModuleImpl<CasperConfig, CasperMemo>`
|
|
14
|
+
— which keeps the precise shape, so a caller sees exactly which methods exist — and omits the
|
|
15
|
+
eight capabilities Casper does not expose: block queries (`getBlock`, `getBlockInfo`), `call`,
|
|
16
|
+
`register`, staking (`getValidators`, `getStakes`, `getRewards`) and `craftRawTransaction`.
|
|
17
|
+
|
|
18
|
+
`craftTransactionData` is the interesting one and is _not_ omitted. It is the single
|
|
19
|
+
unsupported method the contract requires, so the type will not let it be dropped; it stays
|
|
20
|
+
declared, now built with the framework's `notSupported()` helper rather than an inline throw.
|
|
21
|
+
That keeps the distinction the migration is about visible in the source: eight absent
|
|
22
|
+
capabilities on one side, one required method this module does not implement on the other.
|
|
23
|
+
|
|
24
|
+
`getNextSequence` keeps its real implementation returning `0n` — Casper uses transaction hash
|
|
25
|
+
plus TTL for replay protection rather than a per-account nonce, so zero is an answer, not a
|
|
26
|
+
placeholder.
|
|
27
|
+
|
|
28
|
+
Callers see no change: the resolver's `withDefaults` supplies every omitted capability, so the
|
|
29
|
+
same call raises the same error from one place. What improves is introspection — `supports()`
|
|
30
|
+
can now tell these capabilities are absent, which was impossible while a throwing placeholder
|
|
31
|
+
occupied the slot and looked exactly like an implementation.
|
|
32
|
+
|
|
33
|
+
The authored type also keeps the contract's trailing optional parameter, or a caller reaching the module through it could no longer pass it: `broadcast` accepts and ignores its own. TypeScript does not hold a function's shorter parameter list against a target declaring more, so the `satisfies` passed either way and nothing flagged the narrowing.
|
|
34
|
+
|
|
35
|
+
- Updated dependencies [[`27388a8`](https://github.com/LedgerHQ/ledger-live/commit/27388a894eaac67b8e162a60f6d3368aad0a8682)]:
|
|
36
|
+
- @ledgerhq/types-live@6.122.0-nightly.20260901020738
|
|
37
|
+
- @ledgerhq/ledger-wallet-framework@3.2.0-nightly.20260901020738
|
|
38
|
+
|
|
3
39
|
## 3.1.0
|
|
4
40
|
|
|
5
41
|
### Minor Changes
|
package/jest.config.js
CHANGED
|
@@ -24,6 +24,11 @@ module.exports = {
|
|
|
24
24
|
"default",
|
|
25
25
|
...(process.env.CI ? ["github-actions"] : []),
|
|
26
26
|
["jest-sonar", { outputName: "sonar-executionTests-report.xml", reportedFilePath: "absolute" }],
|
|
27
|
+
"@ledgerhq/test-quarantine/jest",
|
|
28
|
+
],
|
|
29
|
+
setupFilesAfterEnv: [
|
|
30
|
+
"@ledgerhq/wallet-framework-test-setup",
|
|
31
|
+
"@ledgerhq/disable-network-setup",
|
|
32
|
+
"@ledgerhq/test-quarantine/jest-retries",
|
|
27
33
|
],
|
|
28
|
-
setupFilesAfterEnv: ["@ledgerhq/wallet-framework-test-setup", "@ledgerhq/disable-network-setup"],
|
|
29
34
|
};
|
package/lib/api/index.d.ts
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
3
|
-
|
|
1
|
+
import type { Balance, BalanceOptions } from "@ledgerhq/coin-module-framework/api/index";
|
|
2
|
+
import { lastBlock } from "../logic/lastBlock";
|
|
3
|
+
import { listOperations } from "../logic/listOperations";
|
|
4
|
+
import { estimateFees } from "../logic/estimateFees";
|
|
5
|
+
import type { CasperConfig, CasperContext, CasperMemo } from "../types";
|
|
6
|
+
export declare function createApi(): {
|
|
7
|
+
lastBlock: typeof lastBlock;
|
|
8
|
+
getBalance(context: CasperContext, address: string, options?: BalanceOptions): Promise<Balance[]>;
|
|
9
|
+
listOperations: typeof listOperations;
|
|
10
|
+
craftTransaction: (_context: import("@ledgerhq/coin-module-framework/lib/config").Context<CasperConfig>, transactionIntent: import("@ledgerhq/coin-module-framework/lib/api/types").TransactionIntent<CasperMemo, import("@ledgerhq/coin-module-framework/lib/api/types").TxDataNotSupported>, options?: {
|
|
11
|
+
customFees?: import("@ledgerhq/coin-module-framework/lib/api/types").FeeEstimation;
|
|
12
|
+
} | undefined) => Promise<import("@ledgerhq/coin-module-framework/lib/api/types").CraftedTransaction>;
|
|
13
|
+
combine: (_context: import("@ledgerhq/coin-module-framework/lib/config").Context<CasperConfig>, tx: string, signature: string[], options?: {
|
|
14
|
+
pubkey?: string;
|
|
15
|
+
} | undefined) => string;
|
|
16
|
+
broadcast: (context: import("@ledgerhq/coin-module-framework/lib/config").Context<CasperConfig>, tx: string, _options?: {
|
|
17
|
+
broadcastConfig?: import("@ledgerhq/coin-module-framework/lib/api/types").BroadcastConfig;
|
|
18
|
+
} | undefined) => Promise<string>;
|
|
19
|
+
estimateFees: typeof estimateFees;
|
|
20
|
+
validateIntent: (_context: import("@ledgerhq/coin-module-framework/lib/config").Context<CasperConfig>, intent: import("@ledgerhq/coin-module-framework/lib/api/types").TransactionIntent<CasperMemo, import("@ledgerhq/coin-module-framework/lib/api/types").TxDataNotSupported>, balances: Balance[], options?: {
|
|
21
|
+
customFees?: import("@ledgerhq/coin-module-framework/lib/api/types").FeeEstimation;
|
|
22
|
+
} | undefined) => Promise<import("@ledgerhq/coin-module-framework/lib/api/types").TransactionValidation>;
|
|
23
|
+
getNextSequence: (_context: CasperContext, _address: string) => Promise<bigint>;
|
|
24
|
+
validateAddress: (_context: import("@ledgerhq/coin-module-framework/lib/config").Context<CasperConfig>, address: string, parameters: Partial<import("@ledgerhq/coin-module-framework/lib/api/types").AddressValidationCurrencyParameters>) => Promise<boolean>;
|
|
25
|
+
craftTransactionData: () => never;
|
|
26
|
+
};
|
|
4
27
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/api/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EAEf,MAAM,2CAA2C,CAAC;AAMnD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGrD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAUxE,wBAAgB,SAAS;;wBAIV,aAAa,WACb,MAAM,YACL,cAAc,GACvB,OAAO,CAAC,OAAO,EAAE,CAAC;;;;;;;;;;;;;;;gCAaa,aAAa,YAAY,MAAM;;;EAIpE"}
|
package/lib/api/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createApi = createApi;
|
|
4
|
+
const index_1 = require("@ledgerhq/coin-module-framework/api/index");
|
|
4
5
|
const rejectBalanceOptions_1 = require("@ledgerhq/coin-module-framework/api/getBalance/rejectBalanceOptions");
|
|
5
6
|
const broadcast_1 = require("../logic/broadcast");
|
|
6
7
|
const combine_1 = require("../logic/combine");
|
|
@@ -12,49 +13,30 @@ const estimateFees_1 = require("../logic/estimateFees");
|
|
|
12
13
|
const validateIntent_1 = require("../logic/validateIntent");
|
|
13
14
|
const validateAddress_1 = require("../bridge/validateAddress");
|
|
14
15
|
// The caller builds the {@link CasperContext} (config + logger) and passes it to each method (ADR-019).
|
|
16
|
+
//
|
|
17
|
+
// Casper supports everything the contract requires but `craftTransactionData`, so it declares
|
|
18
|
+
// the authoring type and omits its unsupported *capabilities* — block queries, `call`,
|
|
19
|
+
// `register`, staking and raw crafting — rather than stubbing each one. That distinction is
|
|
20
|
+
// the point: eight omissions are capabilities this chain does not expose, while the stub
|
|
21
|
+
// below is a required method this module does not implement, which the type will not let us
|
|
22
|
+
// omit and which therefore stays visible here.
|
|
15
23
|
function createApi() {
|
|
16
24
|
return {
|
|
17
25
|
lastBlock: lastBlock_1.lastBlock,
|
|
18
|
-
getBlockInfo(_context, _height) {
|
|
19
|
-
throw new Error("getBlockInfo is not supported");
|
|
20
|
-
},
|
|
21
|
-
getBlock(_context, _height) {
|
|
22
|
-
throw new Error("getBlock is not supported");
|
|
23
|
-
},
|
|
24
|
-
async call() {
|
|
25
|
-
throw new Error("call is not supported");
|
|
26
|
-
},
|
|
27
|
-
async register() {
|
|
28
|
-
throw new Error("register is not supported");
|
|
29
|
-
},
|
|
30
|
-
getValidators(_context, _options) {
|
|
31
|
-
throw new Error("getValidators is not supported");
|
|
32
|
-
},
|
|
33
26
|
getBalance(context, address, options) {
|
|
34
27
|
return (0, rejectBalanceOptions_1.rejectBalanceOptions)(() => (0, getBalance_1.getBalance)(context, address), options);
|
|
35
28
|
},
|
|
36
29
|
listOperations: listOperations_1.listOperations,
|
|
37
|
-
getStakes(_context, _address, _options) {
|
|
38
|
-
throw new Error("getStakes is not supported");
|
|
39
|
-
},
|
|
40
|
-
getRewards(_context, _address, _options) {
|
|
41
|
-
throw new Error("getRewards is not supported");
|
|
42
|
-
},
|
|
43
30
|
craftTransaction: (_context, transactionIntent, options) => (0, craftTransaction_1.craftTransaction)(transactionIntent, options?.customFees),
|
|
44
|
-
craftRawTransaction(_context, _transaction, _sender, _publicKey, _sequence) {
|
|
45
|
-
throw new Error("craftRawTransaction is not supported");
|
|
46
|
-
},
|
|
47
31
|
combine: (_context, tx, signature, options) => (0, combine_1.combine)(tx, signature, options?.pubkey),
|
|
48
|
-
broadcast: (context, tx) => (0, broadcast_1.broadcast)(context, tx),
|
|
32
|
+
broadcast: (context, tx, _options) => (0, broadcast_1.broadcast)(context, tx),
|
|
49
33
|
estimateFees: estimateFees_1.estimateFees,
|
|
50
34
|
validateIntent: async (_context, intent, balances, options) => (0, validateIntent_1.validateIntent)(intent, balances, options?.customFees),
|
|
51
35
|
// Casper uses (transaction hash + TTL) for replay protection rather than a
|
|
52
36
|
// per-account nonce, so getNextSequence has no meaningful value here.
|
|
53
37
|
getNextSequence: async (_context, _address) => 0n,
|
|
54
38
|
validateAddress: (_context, address, parameters) => (0, validateAddress_1.validateAddress)(address, parameters),
|
|
55
|
-
craftTransactionData(
|
|
56
|
-
throw new Error("craftTransactionData is not supported");
|
|
57
|
-
},
|
|
39
|
+
craftTransactionData: (0, index_1.notSupported)("craftTransactionData"),
|
|
58
40
|
};
|
|
59
41
|
}
|
|
60
42
|
//# sourceMappingURL=index.js.map
|
package/lib/api/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":";;;AAKA,qEAAyE;AACzE,8GAA2G;AAC3G,kDAA+C;AAC/C,8CAA2C;AAC3C,gEAA6D;AAC7D,kDAA+C;AAC/C,oDAAsE;AACtE,4DAAyD;AACzD,wDAAqD;AACrD,4DAAyD;AACzD,+DAA4D;AAG5D,wGAAwG;AACxG,EAAE;AACF,8FAA8F;AAC9F,uFAAuF;AACvF,4FAA4F;AAC5F,yFAAyF;AACzF,4FAA4F;AAC5F,+CAA+C;AAC/C;IACE,OAAO;QACL,SAAS,EAAT,qBAAS;QACT,UAAU,CACR,OAAsB,EACtB,OAAe,EACf,OAAwB;YAExB,OAAO,IAAA,2CAAoB,EAAC,GAAG,EAAE,CAAC,IAAA,uBAAiB,EAAC,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;QAClF,CAAC;QACD,cAAc,EAAd,+BAAc;QACd,gBAAgB,EAAE,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAQ,EAAE,EAAE,CAC1D,IAAA,mCAAgB,EAAC,iBAAiB,EAAE,OAAO,EAAE,UAAU,CAAC;QAC1D,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,OAAQ,EAAE,EAAE,CAAC,IAAA,iBAAO,EAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC;QACvF,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,EAAE,QAAS,EAAE,EAAE,CAAC,IAAA,qBAAS,EAAC,OAAO,EAAE,EAAE,CAAC;QAC7D,YAAY,EAAZ,2BAAY;QACZ,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAQ,EAAE,EAAE,CAC7D,IAAA,+BAAc,EAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC;QACvD,2EAA2E;QAC3E,sEAAsE;QACtE,eAAe,EAAE,KAAK,EAAE,QAAuB,EAAE,QAAgB,EAAE,EAAE,CAAC,EAAE;QACxE,eAAe,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,CAAC,IAAA,iCAAe,EAAC,OAAO,EAAE,UAAU,CAAC;QACxF,oBAAoB,EAAE,IAAA,oBAAY,EAAC,sBAAsB,CAAC;KACR,CAAC;AACvD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"craftTransaction.d.ts","sourceRoot":"","sources":["../../src/logic/craftTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EAClB,MAAM,2CAA2C,CAAC;AAMnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAM3C,wBAAsB,gBAAgB,CACpC,iBAAiB,EAAE,iBAAiB,CAAC,UAAU,CAAC,EAChD,UAAU,CAAC,EAAE,aAAa,GACzB,OAAO,CAAC,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"craftTransaction.d.ts","sourceRoot":"","sources":["../../src/logic/craftTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EAClB,MAAM,2CAA2C,CAAC;AAMnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAM3C,wBAAsB,gBAAgB,CACpC,iBAAiB,EAAE,iBAAiB,CAAC,UAAU,CAAC,EAChD,UAAU,CAAC,EAAE,aAAa,GACzB,OAAO,CAAC,kBAAkB,CAAC,CA8C7B"}
|
|
@@ -23,8 +23,7 @@ async function craftTransaction(transactionIntent, customFees) {
|
|
|
23
23
|
if (!(0, validateAddress_1.isAddressValid)(recipient)) {
|
|
24
24
|
throw new errors_1.InvalidAddress(`Invalid recipient Address ${recipient}`);
|
|
25
25
|
}
|
|
26
|
-
const
|
|
27
|
-
const transferId = memo?.type === "string" && memo.kind === "transferId" ? memo.value : undefined;
|
|
26
|
+
const transferId = (0, utils_1.getTransferIdFromMemo)("memo" in transactionIntent ? transactionIntent.memo : undefined);
|
|
28
27
|
if (typeof transferId === "string" && transferId.length > 0 && !(0, validateMemo_1.validateMemo)(transferId)) {
|
|
29
28
|
throw new errors_2.CasperInvalidTransferId("", {
|
|
30
29
|
maxTransferId: constants_1.CASPER_MAX_TRANSFER_ID,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"craftTransaction.js","sourceRoot":"","sources":["../../src/logic/craftTransaction.ts"],"names":[],"mappings":";;;;;;AAKA,qEAA0E;AAC1E,iDAAiE;AACjE,0DAAkC;AAClC,4CAA0F;AAC1F,sCAAoD;AAEpD,iDAAkD;AAClD,
|
|
1
|
+
{"version":3,"file":"craftTransaction.js","sourceRoot":"","sources":["../../src/logic/craftTransaction.ts"],"names":[],"mappings":";;;;;;AAKA,qEAA0E;AAC1E,iDAAiE;AACjE,0DAAkC;AAClC,4CAA0F;AAC1F,sCAAoD;AAEpD,iDAAkD;AAClD,mCAA8D;AAC9D,uDAAmD;AACnD,iDAA8C;AAEvC,KAAK,2BACV,iBAAgD,EAChD,UAA0B;IAE1B,IAAA,mBAAS,EAAC,iBAAiB,CAAC,UAAU,KAAK,SAAS,EAAE,kCAAkC,CAAC,CAAC;IAC1F,IAAA,mBAAS,EACP,iBAAiB,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,EACzC,wCAAwC,EACxC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAC7B,CAAC;IAEF,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,iBAAiB,CAAC;IAEpE,IAAI,CAAC,IAAA,gCAAc,EAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,uBAAc,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,CAAC,IAAA,gCAAc,EAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,uBAAc,CAAC,6BAA6B,SAAS,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,UAAU,GAAG,IAAA,6BAAqB,EACtC,MAAM,IAAI,iBAAiB,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CACjE,CAAC;IAEF,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAA,2BAAY,EAAC,UAAU,CAAC,EAAE,CAAC;QACzF,MAAM,IAAI,gCAAuB,CAAC,EAAE,EAAE;YACpC,aAAa,EAAE,kCAAsB;SACtC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,IAAA,oBAAY,EAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAA,+BAAgB,GAAE,CAAC,QAAQ,EAAE,CAAC;IAEjG,MAAM,OAAO,GAAG,IAAI,qCAAqB,EAAE;SACxC,IAAI,CAAC,yBAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;SAC/B,MAAM,CAAC,yBAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;SACpC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;SACzB,SAAS,CAAC,0BAAc,CAAC;SACzB,OAAO,CAAC,YAAY,CAAC;SACrB,GAAG,CAAC,UAAU,IAAI,8BAAkB,CAAC,CAAC;IAEzC,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5D,qGAAqG;QACrG,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAE3B,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;AACtD,CAAC"}
|
package/lib/logic/utils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CasperMemo } from "../types";
|
|
1
2
|
export declare const isNoErrorReturnCode: (code: number) => boolean;
|
|
2
3
|
export declare const getPath: (path: string) => string;
|
|
3
4
|
export declare const isValidHex: (msg: string) => boolean;
|
|
@@ -10,4 +11,5 @@ export declare const methodToString: (method: number) => string;
|
|
|
10
11
|
export declare const getBufferFromString: (message: string) => Buffer;
|
|
11
12
|
export declare function getRandomTransferID(): string;
|
|
12
13
|
export declare function toSafeNumber(value: bigint): number;
|
|
14
|
+
export declare function getTransferIdFromMemo(memo: CasperMemo | undefined): string | undefined;
|
|
13
15
|
//# sourceMappingURL=utils.d.ts.map
|
package/lib/logic/utils.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/logic/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/logic/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAO3C,eAAO,MAAM,mBAAmB,SAAU,MAAM,KAAG,OAA0B,CAAC;AAE9E,eAAO,MAAM,OAAO,SAAU,MAAM,KAAG,MACc,CAAC;AAEtD,eAAO,MAAM,UAAU,QAAS,MAAM,KAAG,OAAmC,CAAC;AAC7E,eAAO,MAAM,aAAa,QAAS,MAAM,KAAG,OAAsC,CAAC;AAEnF,eAAO,MAAM,OAAO,MAAO;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,KAAG,IAEzE,CAAC;AAEF,eAAO,MAAM,cAAc,WAAY,MAAM,KAAG,MAG/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,YAAa,MAAM,KAAG,MAUrD,CAAC;AAYF,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD;AAGD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAKtF"}
|
package/lib/logic/utils.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.getBufferFromString = exports.methodToString = exports.isError = exports.isValidBase64 = exports.isValidHex = exports.getPath = exports.isNoErrorReturnCode = void 0;
|
|
7
7
|
exports.getRandomTransferID = getRandomTransferID;
|
|
8
8
|
exports.toSafeNumber = toSafeNumber;
|
|
9
|
+
exports.getTransferIdFromMemo = getTransferIdFromMemo;
|
|
9
10
|
const bignumber_js_1 = __importDefault(require("bignumber.js"));
|
|
10
11
|
const validHexRegExp = new RegExp(/[0-9A-Fa-f]{6}/g);
|
|
11
12
|
const validBase64RegExp = new RegExp(/^(?:[A-Za-z\d+/]{4})*(?:[A-Za-z\d+/]{3}=|[A-Za-z\d+/]{2}==)?$/);
|
|
@@ -54,4 +55,14 @@ function toSafeNumber(value) {
|
|
|
54
55
|
}
|
|
55
56
|
return Number(value);
|
|
56
57
|
}
|
|
58
|
+
// Two memo shapes coexist until LIVE-35735 unifies them.
|
|
59
|
+
function getTransferIdFromMemo(memo) {
|
|
60
|
+
if (!memo)
|
|
61
|
+
return undefined;
|
|
62
|
+
if (memo.type === "string" && memo.kind === "transferId")
|
|
63
|
+
return memo.value;
|
|
64
|
+
if (memo.type === "transferId")
|
|
65
|
+
return memo.value;
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
57
68
|
//# sourceMappingURL=utils.js.map
|
package/lib/logic/utils.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/logic/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/logic/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateIntent.d.ts","sourceRoot":"","sources":["../../src/logic/validateIntent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,2CAA2C,CAAC;AAgBnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"validateIntent.d.ts","sourceRoot":"","sources":["../../src/logic/validateIntent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,2CAA2C,CAAC;AAgBnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAqE3C,wBAAgB,cAAc,CAC5B,MAAM,EAAE,iBAAiB,CAAC,UAAU,CAAC,EACrC,QAAQ,EAAE,OAAO,EAAE,EACnB,UAAU,CAAC,EAAE,aAAa,GACzB,qBAAqB,CA4CvB"}
|
|
@@ -8,6 +8,7 @@ const errors_1 = require("@ledgerhq/ledger-wallet-framework/errors");
|
|
|
8
8
|
const invariant_1 = __importDefault(require("invariant"));
|
|
9
9
|
const constants_1 = require("../constants");
|
|
10
10
|
const errors_2 = require("../errors");
|
|
11
|
+
const utils_1 = require("./utils");
|
|
11
12
|
const validateAddress_1 = require("./validateAddress");
|
|
12
13
|
const validateMemo_1 = require("./validateMemo");
|
|
13
14
|
const MIN_VALID_AMOUNT_MOTES = BigInt(constants_1.CASPER_MINIMUM_VALID_AMOUNT_MOTES);
|
|
@@ -65,8 +66,7 @@ function validateIntent(intent, balances, customFees) {
|
|
|
65
66
|
const nativeBalance = balances.find(b => b.asset.type === "native");
|
|
66
67
|
const balance = nativeBalance?.value ?? 0n;
|
|
67
68
|
const spendableBalance = balance - (nativeBalance?.locked ?? 0n);
|
|
68
|
-
const
|
|
69
|
-
const transferId = memo?.type === "string" && memo.kind === "transferId" ? memo.value : undefined;
|
|
69
|
+
const transferId = (0, utils_1.getTransferIdFromMemo)("memo" in intent ? intent.memo : undefined);
|
|
70
70
|
validateRecipient(recipient, sender, currencyName, errors);
|
|
71
71
|
validateSender(sender, transferId, currencyName, errors);
|
|
72
72
|
const estimatedFees = customFees?.value ?? 0n;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateIntent.js","sourceRoot":"","sources":["../../src/logic/validateIntent.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"validateIntent.js","sourceRoot":"","sources":["../../src/logic/validateIntent.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import { MemoNotSupported, StringMemo } from "@ledgerhq/coin-module-framework/api/types";
|
|
2
|
-
export
|
|
2
|
+
export interface FrameworkTransferIdMemo {
|
|
3
|
+
type: "transferId";
|
|
4
|
+
value: string;
|
|
5
|
+
}
|
|
6
|
+
export type CasperMemo = MemoNotSupported | StringMemo<"transferId"> | FrameworkTransferIdMemo;
|
|
3
7
|
//# sourceMappingURL=coinframework.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coinframework.d.ts","sourceRoot":"","sources":["../../src/types/coinframework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"coinframework.d.ts","sourceRoot":"","sources":["../../src/types/coinframework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,2CAA2C,CAAC;AAGzF,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,UAAU,GAAG,gBAAgB,GAAG,UAAU,CAAC,YAAY,CAAC,GAAG,uBAAuB,CAAC"}
|
package/lib-es/api/index.d.ts
CHANGED
|
@@ -1,4 +1,27 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import
|
|
3
|
-
|
|
1
|
+
import type { Balance, BalanceOptions } from "@ledgerhq/coin-module-framework/api/index";
|
|
2
|
+
import { lastBlock } from "../logic/lastBlock";
|
|
3
|
+
import { listOperations } from "../logic/listOperations";
|
|
4
|
+
import { estimateFees } from "../logic/estimateFees";
|
|
5
|
+
import type { CasperConfig, CasperContext, CasperMemo } from "../types";
|
|
6
|
+
export declare function createApi(): {
|
|
7
|
+
lastBlock: typeof lastBlock;
|
|
8
|
+
getBalance(context: CasperContext, address: string, options?: BalanceOptions): Promise<Balance[]>;
|
|
9
|
+
listOperations: typeof listOperations;
|
|
10
|
+
craftTransaction: (_context: import("@ledgerhq/coin-module-framework/lib-es/config").Context<CasperConfig>, transactionIntent: import("@ledgerhq/coin-module-framework/lib-es/api/types").TransactionIntent<CasperMemo, import("@ledgerhq/coin-module-framework/lib-es/api/types").TxDataNotSupported>, options?: {
|
|
11
|
+
customFees?: import("@ledgerhq/coin-module-framework/lib-es/api/types").FeeEstimation;
|
|
12
|
+
} | undefined) => Promise<import("@ledgerhq/coin-module-framework/lib-es/api/types").CraftedTransaction>;
|
|
13
|
+
combine: (_context: import("@ledgerhq/coin-module-framework/lib-es/config").Context<CasperConfig>, tx: string, signature: string[], options?: {
|
|
14
|
+
pubkey?: string;
|
|
15
|
+
} | undefined) => string;
|
|
16
|
+
broadcast: (context: import("@ledgerhq/coin-module-framework/lib-es/config").Context<CasperConfig>, tx: string, _options?: {
|
|
17
|
+
broadcastConfig?: import("@ledgerhq/coin-module-framework/lib-es/api/types").BroadcastConfig;
|
|
18
|
+
} | undefined) => Promise<string>;
|
|
19
|
+
estimateFees: typeof estimateFees;
|
|
20
|
+
validateIntent: (_context: import("@ledgerhq/coin-module-framework/lib-es/config").Context<CasperConfig>, intent: import("@ledgerhq/coin-module-framework/lib-es/api/types").TransactionIntent<CasperMemo, import("@ledgerhq/coin-module-framework/lib-es/api/types").TxDataNotSupported>, balances: Balance[], options?: {
|
|
21
|
+
customFees?: import("@ledgerhq/coin-module-framework/lib-es/api/types").FeeEstimation;
|
|
22
|
+
} | undefined) => Promise<import("@ledgerhq/coin-module-framework/lib-es/api/types").TransactionValidation>;
|
|
23
|
+
getNextSequence: (_context: CasperContext, _address: string) => Promise<bigint>;
|
|
24
|
+
validateAddress: (_context: import("@ledgerhq/coin-module-framework/lib-es/config").Context<CasperConfig>, address: string, parameters: Partial<import("@ledgerhq/coin-module-framework/lib-es/api/types").AddressValidationCurrencyParameters>) => Promise<boolean>;
|
|
25
|
+
craftTransactionData: () => never;
|
|
26
|
+
};
|
|
4
27
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,cAAc,EAEf,MAAM,2CAA2C,CAAC;AAMnD,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAGrD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAUxE,wBAAgB,SAAS;;wBAIV,aAAa,WACb,MAAM,YACL,cAAc,GACvB,OAAO,CAAC,OAAO,EAAE,CAAC;;;;;;;;;;;;;;;gCAaa,aAAa,YAAY,MAAM;;;EAIpE"}
|
package/lib-es/api/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { notSupported } from "@ledgerhq/coin-module-framework/api/index";
|
|
1
2
|
import { rejectBalanceOptions } from "@ledgerhq/coin-module-framework/api/getBalance/rejectBalanceOptions";
|
|
2
3
|
import { broadcast } from "../logic/broadcast";
|
|
3
4
|
import { combine } from "../logic/combine";
|
|
@@ -9,49 +10,30 @@ import { estimateFees } from "../logic/estimateFees";
|
|
|
9
10
|
import { validateIntent } from "../logic/validateIntent";
|
|
10
11
|
import { validateAddress } from "../bridge/validateAddress";
|
|
11
12
|
// The caller builds the {@link CasperContext} (config + logger) and passes it to each method (ADR-019).
|
|
13
|
+
//
|
|
14
|
+
// Casper supports everything the contract requires but `craftTransactionData`, so it declares
|
|
15
|
+
// the authoring type and omits its unsupported *capabilities* — block queries, `call`,
|
|
16
|
+
// `register`, staking and raw crafting — rather than stubbing each one. That distinction is
|
|
17
|
+
// the point: eight omissions are capabilities this chain does not expose, while the stub
|
|
18
|
+
// below is a required method this module does not implement, which the type will not let us
|
|
19
|
+
// omit and which therefore stays visible here.
|
|
12
20
|
export function createApi() {
|
|
13
21
|
return {
|
|
14
22
|
lastBlock,
|
|
15
|
-
getBlockInfo(_context, _height) {
|
|
16
|
-
throw new Error("getBlockInfo is not supported");
|
|
17
|
-
},
|
|
18
|
-
getBlock(_context, _height) {
|
|
19
|
-
throw new Error("getBlock is not supported");
|
|
20
|
-
},
|
|
21
|
-
async call() {
|
|
22
|
-
throw new Error("call is not supported");
|
|
23
|
-
},
|
|
24
|
-
async register() {
|
|
25
|
-
throw new Error("register is not supported");
|
|
26
|
-
},
|
|
27
|
-
getValidators(_context, _options) {
|
|
28
|
-
throw new Error("getValidators is not supported");
|
|
29
|
-
},
|
|
30
23
|
getBalance(context, address, options) {
|
|
31
24
|
return rejectBalanceOptions(() => getAccountBalance(context, address), options);
|
|
32
25
|
},
|
|
33
26
|
listOperations,
|
|
34
|
-
getStakes(_context, _address, _options) {
|
|
35
|
-
throw new Error("getStakes is not supported");
|
|
36
|
-
},
|
|
37
|
-
getRewards(_context, _address, _options) {
|
|
38
|
-
throw new Error("getRewards is not supported");
|
|
39
|
-
},
|
|
40
27
|
craftTransaction: (_context, transactionIntent, options) => craftTransaction(transactionIntent, options?.customFees),
|
|
41
|
-
craftRawTransaction(_context, _transaction, _sender, _publicKey, _sequence) {
|
|
42
|
-
throw new Error("craftRawTransaction is not supported");
|
|
43
|
-
},
|
|
44
28
|
combine: (_context, tx, signature, options) => combine(tx, signature, options?.pubkey),
|
|
45
|
-
broadcast: (context, tx) => broadcast(context, tx),
|
|
29
|
+
broadcast: (context, tx, _options) => broadcast(context, tx),
|
|
46
30
|
estimateFees,
|
|
47
31
|
validateIntent: async (_context, intent, balances, options) => validateIntent(intent, balances, options?.customFees),
|
|
48
32
|
// Casper uses (transaction hash + TTL) for replay protection rather than a
|
|
49
33
|
// per-account nonce, so getNextSequence has no meaningful value here.
|
|
50
34
|
getNextSequence: async (_context, _address) => 0n,
|
|
51
35
|
validateAddress: (_context, address, parameters) => validateAddress(address, parameters),
|
|
52
|
-
craftTransactionData(
|
|
53
|
-
throw new Error("craftTransactionData is not supported");
|
|
54
|
-
},
|
|
36
|
+
craftTransactionData: notSupported("craftTransactionData"),
|
|
55
37
|
};
|
|
56
38
|
}
|
|
57
39
|
//# sourceMappingURL=index.js.map
|
package/lib-es/api/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AACzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,qEAAqE,CAAC;AAC3G,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,IAAI,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAG5D,wGAAwG;AACxG,EAAE;AACF,8FAA8F;AAC9F,uFAAuF;AACvF,4FAA4F;AAC5F,yFAAyF;AACzF,4FAA4F;AAC5F,+CAA+C;AAC/C,MAAM,UAAU,SAAS;IACvB,OAAO;QACL,SAAS;QACT,UAAU,CACR,OAAsB,EACtB,OAAe,EACf,OAAwB;YAExB,OAAO,oBAAoB,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,CAAC;QAClF,CAAC;QACD,cAAc;QACd,gBAAgB,EAAE,CAAC,QAAQ,EAAE,iBAAiB,EAAE,OAAQ,EAAE,EAAE,CAC1D,gBAAgB,CAAC,iBAAiB,EAAE,OAAO,EAAE,UAAU,CAAC;QAC1D,OAAO,EAAE,CAAC,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,OAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,CAAC;QACvF,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,EAAE,QAAS,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,CAAC;QAC7D,YAAY;QACZ,cAAc,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAQ,EAAE,EAAE,CAC7D,cAAc,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC;QACvD,2EAA2E;QAC3E,sEAAsE;QACtE,eAAe,EAAE,KAAK,EAAE,QAAuB,EAAE,QAAgB,EAAE,EAAE,CAAC,EAAE;QACxE,eAAe,EAAE,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE,UAAU,CAAC;QACxF,oBAAoB,EAAE,YAAY,CAAC,sBAAsB,CAAC;KACR,CAAC;AACvD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"craftTransaction.d.ts","sourceRoot":"","sources":["../../src/logic/craftTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EAClB,MAAM,2CAA2C,CAAC;AAMnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAM3C,wBAAsB,gBAAgB,CACpC,iBAAiB,EAAE,iBAAiB,CAAC,UAAU,CAAC,EAChD,UAAU,CAAC,EAAE,aAAa,GACzB,OAAO,CAAC,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"craftTransaction.d.ts","sourceRoot":"","sources":["../../src/logic/craftTransaction.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACb,iBAAiB,EAClB,MAAM,2CAA2C,CAAC;AAMnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAM3C,wBAAsB,gBAAgB,CACpC,iBAAiB,EAAE,iBAAiB,CAAC,UAAU,CAAC,EAChD,UAAU,CAAC,EAAE,aAAa,GACzB,OAAO,CAAC,kBAAkB,CAAC,CA8C7B"}
|
|
@@ -4,7 +4,7 @@ import invariant from "invariant";
|
|
|
4
4
|
import { CASPER_DEFAULT_TTL, CASPER_MAX_TRANSFER_ID, CASPER_NETWORK } from "../constants";
|
|
5
5
|
import { CasperInvalidTransferId } from "../errors";
|
|
6
6
|
import { getEstimatedFees } from "./estimateFees";
|
|
7
|
-
import { toSafeNumber } from "./utils";
|
|
7
|
+
import { getTransferIdFromMemo, toSafeNumber } from "./utils";
|
|
8
8
|
import { isAddressValid } from "./validateAddress";
|
|
9
9
|
import { validateMemo } from "./validateMemo";
|
|
10
10
|
export async function craftTransaction(transactionIntent, customFees) {
|
|
@@ -17,8 +17,7 @@ export async function craftTransaction(transactionIntent, customFees) {
|
|
|
17
17
|
if (!isAddressValid(recipient)) {
|
|
18
18
|
throw new InvalidAddress(`Invalid recipient Address ${recipient}`);
|
|
19
19
|
}
|
|
20
|
-
const
|
|
21
|
-
const transferId = memo?.type === "string" && memo.kind === "transferId" ? memo.value : undefined;
|
|
20
|
+
const transferId = getTransferIdFromMemo("memo" in transactionIntent ? transactionIntent.memo : undefined);
|
|
22
21
|
if (typeof transferId === "string" && transferId.length > 0 && !validateMemo(transferId)) {
|
|
23
22
|
throw new CasperInvalidTransferId("", {
|
|
24
23
|
maxTransferId: CASPER_MAX_TRANSFER_ID,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"craftTransaction.js","sourceRoot":"","sources":["../../src/logic/craftTransaction.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1F,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAEpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"craftTransaction.js","sourceRoot":"","sources":["../../src/logic/craftTransaction.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,cAAc,EAAE,MAAM,0CAA0C,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1F,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAEpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,iBAAgD,EAChD,UAA0B;IAE1B,SAAS,CAAC,iBAAiB,CAAC,UAAU,KAAK,SAAS,EAAE,kCAAkC,CAAC,CAAC;IAC1F,SAAS,CACP,iBAAiB,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,EACzC,wCAAwC,EACxC,iBAAiB,CAAC,KAAK,CAAC,IAAI,CAC7B,CAAC;IAEF,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,iBAAiB,CAAC;IAEpE,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,cAAc,CAAC,0BAA0B,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,cAAc,CAAC,6BAA6B,SAAS,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,UAAU,GAAG,qBAAqB,CACtC,MAAM,IAAI,iBAAiB,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CACjE,CAAC;IAEF,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC;QACzF,MAAM,IAAI,uBAAuB,CAAC,EAAE,EAAE;YACpC,aAAa,EAAE,sBAAsB;SACtC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,gBAAgB,EAAE,CAAC,QAAQ,EAAE,CAAC;IAEjG,MAAM,OAAO,GAAG,IAAI,qBAAqB,EAAE;SACxC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;SAC/B,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;SACpC,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;SACzB,SAAS,CAAC,cAAc,CAAC;SACzB,OAAO,CAAC,YAAY,CAAC;SACrB,GAAG,CAAC,UAAU,IAAI,kBAAkB,CAAC,CAAC;IAEzC,IAAI,OAAO,UAAU,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5D,qGAAqG;QACrG,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC;IACzB,CAAC;IAED,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAE3B,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC;AACtD,CAAC"}
|
package/lib-es/logic/utils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { CasperMemo } from "../types";
|
|
1
2
|
export declare const isNoErrorReturnCode: (code: number) => boolean;
|
|
2
3
|
export declare const getPath: (path: string) => string;
|
|
3
4
|
export declare const isValidHex: (msg: string) => boolean;
|
|
@@ -10,4 +11,5 @@ export declare const methodToString: (method: number) => string;
|
|
|
10
11
|
export declare const getBufferFromString: (message: string) => Buffer;
|
|
11
12
|
export declare function getRandomTransferID(): string;
|
|
12
13
|
export declare function toSafeNumber(value: bigint): number;
|
|
14
|
+
export declare function getTransferIdFromMemo(memo: CasperMemo | undefined): string | undefined;
|
|
13
15
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/logic/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/logic/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAO3C,eAAO,MAAM,mBAAmB,SAAU,MAAM,KAAG,OAA0B,CAAC;AAE9E,eAAO,MAAM,OAAO,SAAU,MAAM,KAAG,MACc,CAAC;AAEtD,eAAO,MAAM,UAAU,QAAS,MAAM,KAAG,OAAmC,CAAC;AAC7E,eAAO,MAAM,aAAa,QAAS,MAAM,KAAG,OAAsC,CAAC;AAEnF,eAAO,MAAM,OAAO,MAAO;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,KAAG,IAEzE,CAAC;AAEF,eAAO,MAAM,cAAc,WAAY,MAAM,KAAG,MAG/C,CAAC;AAEF,eAAO,MAAM,mBAAmB,YAAa,MAAM,KAAG,MAUrD,CAAC;AAYF,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD;AAGD,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAKtF"}
|
package/lib-es/logic/utils.js
CHANGED
|
@@ -39,4 +39,14 @@ export function toSafeNumber(value) {
|
|
|
39
39
|
}
|
|
40
40
|
return Number(value);
|
|
41
41
|
}
|
|
42
|
+
// Two memo shapes coexist until LIVE-35735 unifies them.
|
|
43
|
+
export function getTransferIdFromMemo(memo) {
|
|
44
|
+
if (!memo)
|
|
45
|
+
return undefined;
|
|
46
|
+
if (memo.type === "string" && memo.kind === "transferId")
|
|
47
|
+
return memo.value;
|
|
48
|
+
if (memo.type === "transferId")
|
|
49
|
+
return memo.value;
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
42
52
|
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/logic/utils.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/logic/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateIntent.d.ts","sourceRoot":"","sources":["../../src/logic/validateIntent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,2CAA2C,CAAC;AAgBnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"validateIntent.d.ts","sourceRoot":"","sources":["../../src/logic/validateIntent.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,qBAAqB,EACtB,MAAM,2CAA2C,CAAC;AAgBnD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAqE3C,wBAAgB,cAAc,CAC5B,MAAM,EAAE,iBAAiB,CAAC,UAAU,CAAC,EACrC,QAAQ,EAAE,OAAO,EAAE,EACnB,UAAU,CAAC,EAAE,aAAa,GACzB,qBAAqB,CA4CvB"}
|
|
@@ -2,6 +2,7 @@ import { AmountRequired, InvalidAddress, InvalidAddressBecauseDestinationIsAlsoS
|
|
|
2
2
|
import invariant from "invariant";
|
|
3
3
|
import { CASPER_MAX_TRANSFER_ID, CASPER_MINIMUM_VALID_AMOUNT_MOTES, InvalidMinimumAmountError, MayBlockAccountError, } from "../constants";
|
|
4
4
|
import { CasperInvalidTransferId } from "../errors";
|
|
5
|
+
import { getTransferIdFromMemo } from "./utils";
|
|
5
6
|
import { isAddressValid } from "./validateAddress";
|
|
6
7
|
import { validateMemo } from "./validateMemo";
|
|
7
8
|
const MIN_VALID_AMOUNT_MOTES = BigInt(CASPER_MINIMUM_VALID_AMOUNT_MOTES);
|
|
@@ -59,8 +60,7 @@ export function validateIntent(intent, balances, customFees) {
|
|
|
59
60
|
const nativeBalance = balances.find(b => b.asset.type === "native");
|
|
60
61
|
const balance = nativeBalance?.value ?? 0n;
|
|
61
62
|
const spendableBalance = balance - (nativeBalance?.locked ?? 0n);
|
|
62
|
-
const
|
|
63
|
-
const transferId = memo?.type === "string" && memo.kind === "transferId" ? memo.value : undefined;
|
|
63
|
+
const transferId = getTransferIdFromMemo("memo" in intent ? intent.memo : undefined);
|
|
64
64
|
validateRecipient(recipient, sender, currencyName, errors);
|
|
65
65
|
validateSender(sender, transferId, currencyName, errors);
|
|
66
66
|
const estimatedFees = customFees?.value ?? 0n;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"validateIntent.js","sourceRoot":"","sources":["../../src/logic/validateIntent.ts"],"names":[],"mappings":"AAMA,OAAO,EACL,cAAc,EACd,cAAc,EACd,4CAA4C,EAC5C,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,0CAA0C,CAAC;AAClD,OAAO,SAAS,MAAM,WAAW,CAAC;AAClC,OAAO,EACL,sBAAsB,EACtB,iCAAiC,EACjC,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAEpD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,MAAM,sBAAsB,GAAG,MAAM,CAAC,iCAAiC,CAAC,CAAC;AAEzE,SAAS,iBAAiB,CACxB,SAAiB,EACjB,MAAc,EACd,YAAoB,EACpB,MAA6B;IAE7B,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,CAAC,SAAS,GAAG,IAAI,iBAAiB,EAAE,CAAC;IAC7C,CAAC;SAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,CAAC;QACtC,MAAM,CAAC,SAAS,GAAG,IAAI,cAAc,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC;IAC9D,CAAC;SAAM,IAAI,SAAS,CAAC,WAAW,EAAE,KAAK,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;QAC5D,MAAM,CAAC,SAAS,GAAG,IAAI,4CAA4C,EAAE,CAAC;IACxE,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CACrB,MAAc,EACd,UAA8B,EAC9B,YAAoB,EACpB,MAA6B;IAE7B,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,MAAM,CAAC,MAAM,GAAG,IAAI,cAAc,CAAC,EAAE,EAAE,EAAE,YAAY,EAAE,CAAC,CAAC;IAC3D,CAAC;SAAM,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,EAAE,CAAC;QACrC,MAAM,CAAC,MAAM,GAAG,IAAI,uBAAuB,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,sBAAsB,EAAE,CAAC,CAAC;QAC3F,MAAM,CAAC,WAAW,GAAG,IAAI,uBAAuB,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,sBAAsB,EAAE,CAAC,CAAC;IAClG,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CACpB,MAAqC,EACrC,OAAe,EACf,gBAAwB,EACxB,aAAqB,EACrB,MAA6B;IAE7B,IAAI,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC3B,IAAI,UAAkB,CAAC;IAEvB,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACxB,UAAU,GAAG,gBAAgB,CAAC;QAC9B,MAAM,GAAG,UAAU,GAAG,aAAa,CAAC;QACpC,IAAI,MAAM,IAAI,EAAE,IAAI,UAAU,GAAG,OAAO,EAAE,CAAC;YACzC,MAAM,CAAC,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;SAAM,CAAC;QACN,UAAU,GAAG,MAAM,GAAG,aAAa,CAAC;QACpC,IAAI,MAAM,IAAI,EAAE,EAAE,CAAC;YACjB,MAAM,CAAC,MAAM,GAAG,IAAI,cAAc,EAAE,CAAC;QACvC,CAAC;QACD,IAAI,UAAU,GAAG,gBAAgB,EAAE,CAAC;YAClC,MAAM,CAAC,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACzC,CAAC;IACH,CAAC;IAED,IAAI,MAAM,GAAG,sBAAsB,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACtD,MAAM,CAAC,MAAM,GAAG,yBAAyB,CAAC;IAC5C,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,MAAqC,EACrC,QAAmB,EACnB,UAA0B;IAE1B,SAAS,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,EAAE,kCAAkC,CAAC,CAAC;IAC/E,SAAS,CACP,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,EAC9B,wCAAwC,EACxC,MAAM,CAAC,KAAK,CAAC,IAAI,CAClB,CAAC;IAEF,MAAM,MAAM,GAA0B,EAAE,CAAC;IACzC,MAAM,QAAQ,GAA0B,EAAE,CAAC;IAE3C,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,CAAC;IACrC,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,QAAQ,CAAC;IAEnD,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;IACpE,MAAM,OAAO,GAAG,aAAa,EAAE,KAAK,IAAI,EAAE,CAAC;IAC3C,MAAM,gBAAgB,GAAG,OAAO,GAAG,CAAC,aAAa,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC;IAEjE,MAAM,
|
|
1
|
+
{"version":3,"file":"validateIntent.js","sourceRoot":"","sources":["../../src/logic/validateIntent.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import { MemoNotSupported, StringMemo } from "@ledgerhq/coin-module-framework/api/types";
|
|
2
|
-
export
|
|
2
|
+
export interface FrameworkTransferIdMemo {
|
|
3
|
+
type: "transferId";
|
|
4
|
+
value: string;
|
|
5
|
+
}
|
|
6
|
+
export type CasperMemo = MemoNotSupported | StringMemo<"transferId"> | FrameworkTransferIdMemo;
|
|
3
7
|
//# sourceMappingURL=coinframework.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coinframework.d.ts","sourceRoot":"","sources":["../../src/types/coinframework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"coinframework.d.ts","sourceRoot":"","sources":["../../src/types/coinframework.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,2CAA2C,CAAC;AAGzF,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,UAAU,GAAG,gBAAgB,GAAG,UAAU,CAAC,YAAY,CAAC,GAAG,uBAAuB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/coin-casper",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0-nightly.20260901020738",
|
|
4
4
|
"description": "Ledger Casper integration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ledger",
|
|
@@ -94,16 +94,16 @@
|
|
|
94
94
|
},
|
|
95
95
|
"license": "Apache-2.0",
|
|
96
96
|
"dependencies": {
|
|
97
|
-
"@ledgerhq/coin-module-framework": "8.
|
|
97
|
+
"@ledgerhq/coin-module-framework": "8.2.0",
|
|
98
98
|
"@ledgerhq/logs": "6.17.0",
|
|
99
99
|
"bignumber.js": "^9.1.2",
|
|
100
100
|
"casper-js-sdk": "5.0.5",
|
|
101
101
|
"invariant": "^2.2.2",
|
|
102
102
|
"lodash": "4.17.21",
|
|
103
103
|
"rxjs": "7.8.2",
|
|
104
|
-
"@ledgerhq/ledger-wallet-framework": "^3.
|
|
104
|
+
"@ledgerhq/ledger-wallet-framework": "^3.2.0-nightly.20260901020738",
|
|
105
105
|
"@ledgerhq/live-network": "^3.0.0",
|
|
106
|
-
"@ledgerhq/types-live": "^6.
|
|
106
|
+
"@ledgerhq/types-live": "^6.122.0-nightly.20260901020738"
|
|
107
107
|
},
|
|
108
108
|
"devDependencies": {
|
|
109
109
|
"@swc/core": "1.15.11",
|
|
@@ -114,11 +114,12 @@
|
|
|
114
114
|
"@types/node": "24.12.0",
|
|
115
115
|
"@types/semver": "7.7.1",
|
|
116
116
|
"axios": "1.13.5",
|
|
117
|
-
"jest": "30.
|
|
117
|
+
"jest": "30.4.1",
|
|
118
118
|
"oxfmt": "0.64.0",
|
|
119
119
|
"oxlint": "1.79.0",
|
|
120
120
|
"@ledgerhq/disable-network-setup": "^0.3.0",
|
|
121
|
-
"@ledgerhq/
|
|
121
|
+
"@ledgerhq/test-quarantine": "0.0.0",
|
|
122
|
+
"@ledgerhq/wallet-framework-test-setup": "^0.1.8-nightly.20260901020738"
|
|
122
123
|
},
|
|
123
124
|
"scripts": {
|
|
124
125
|
"clean": "rimraf lib lib-es",
|
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
MemoNotSupported,
|
|
5
5
|
TransactionIntent,
|
|
6
6
|
} from "@ledgerhq/coin-module-framework/api/index";
|
|
7
|
+
import { withDefaults } from "@ledgerhq/coin-module-framework/api/index";
|
|
7
8
|
import { createApi } from "./index";
|
|
8
9
|
import { createMockContext } from "../__tests__/fixtures/config.fixture";
|
|
9
10
|
import {
|
|
@@ -39,7 +40,7 @@ describe("Casper Api (mainnet)", () => {
|
|
|
39
40
|
let api: CoinModuleApi<CasperConfig, CasperMemo>;
|
|
40
41
|
|
|
41
42
|
beforeAll(() => {
|
|
42
|
-
api = createApi();
|
|
43
|
+
api = withDefaults(createApi());
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
describe("broadcast", () => {
|
package/src/api/index.test.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import type { Balance, TransactionIntent } from "@ledgerhq/coin-module-framework/api/index";
|
|
2
|
+
import {
|
|
3
|
+
isNotSupportedStub,
|
|
4
|
+
requiredApiKeys,
|
|
5
|
+
withDefaults,
|
|
6
|
+
} from "@ledgerhq/coin-module-framework/api/index";
|
|
2
7
|
import { CASPER_FEES_MOTES } from "../constants";
|
|
3
8
|
import { TEST_ADDRESSES } from "../__tests__/fixtures/addresses.fixture";
|
|
4
9
|
import type { CasperContext, CasperMemo } from "../types";
|
|
@@ -25,32 +30,38 @@ const sendIntent: TransactionIntent<CasperMemo> = {
|
|
|
25
30
|
const balances: Balance[] = [{ value: BALANCE, asset: { type: "native" }, locked: 0n }];
|
|
26
31
|
|
|
27
32
|
describe("createApi", () => {
|
|
28
|
-
it("
|
|
29
|
-
const
|
|
30
|
-
"
|
|
31
|
-
|
|
33
|
+
it("implements every method the contract requires", () => {
|
|
34
|
+
for (const method of requiredApiKeys) {
|
|
35
|
+
expect(typeof api[method]).toBe("function");
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
// The capabilities Casper does not expose are omitted now rather than stubbed one by one,
|
|
40
|
+
// and the resolver's `withDefaults` supplies them — which is also what makes them
|
|
41
|
+
// reportable: a consumer can ask, where a throwing placeholder used to be
|
|
42
|
+
// indistinguishable from an implementation.
|
|
43
|
+
it("omits the capabilities Casper does not expose", () => {
|
|
44
|
+
const resolved = withDefaults(api);
|
|
45
|
+
for (const capability of [
|
|
32
46
|
"getBlock",
|
|
47
|
+
"getBlockInfo",
|
|
33
48
|
"call",
|
|
49
|
+
"register",
|
|
34
50
|
"getValidators",
|
|
35
|
-
"getBalance",
|
|
36
|
-
"listOperations",
|
|
37
51
|
"getStakes",
|
|
38
52
|
"getRewards",
|
|
39
|
-
"craftTransaction",
|
|
40
53
|
"craftRawTransaction",
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
"broadcast",
|
|
44
|
-
"validateIntent",
|
|
45
|
-
"getNextSequence",
|
|
46
|
-
"validateAddress",
|
|
47
|
-
"craftTransactionData",
|
|
48
|
-
];
|
|
49
|
-
for (const method of methods) {
|
|
50
|
-
expect(typeof api[method as keyof typeof api]).toBe("function");
|
|
54
|
+
] as const) {
|
|
55
|
+
expect(resolved.supports(capability)).toBe(false);
|
|
51
56
|
}
|
|
52
57
|
});
|
|
53
58
|
|
|
59
|
+
// `craftTransactionData` is the one unsupported method the contract requires, so it cannot
|
|
60
|
+
// be omitted — it stays declared, and stays visible for what it is.
|
|
61
|
+
it("declares craftTransactionData as unsupported", () => {
|
|
62
|
+
expect(isNotSupportedStub(api.craftTransactionData)).toBe(true);
|
|
63
|
+
});
|
|
64
|
+
|
|
54
65
|
describe("validateIntent", () => {
|
|
55
66
|
it("validates a send intent through the api surface", async () => {
|
|
56
67
|
const result = await api.validateIntent(context, sendIntent, balances, {
|
package/src/api/index.ts
CHANGED
|
@@ -1,17 +1,9 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
Balance,
|
|
3
3
|
BalanceOptions,
|
|
4
|
-
|
|
5
|
-
BlockInfo,
|
|
6
|
-
CoinModuleApi,
|
|
7
|
-
CraftedTransaction,
|
|
8
|
-
Cursor,
|
|
9
|
-
Page,
|
|
10
|
-
Reward,
|
|
11
|
-
Stake,
|
|
12
|
-
TransactionIntent,
|
|
13
|
-
Validator,
|
|
4
|
+
CoinModuleImpl,
|
|
14
5
|
} from "@ledgerhq/coin-module-framework/api/index";
|
|
6
|
+
import { notSupported } from "@ledgerhq/coin-module-framework/api/index";
|
|
15
7
|
import { rejectBalanceOptions } from "@ledgerhq/coin-module-framework/api/getBalance/rejectBalanceOptions";
|
|
16
8
|
import { broadcast } from "../logic/broadcast";
|
|
17
9
|
import { combine } from "../logic/combine";
|
|
@@ -25,27 +17,16 @@ import { validateAddress } from "../bridge/validateAddress";
|
|
|
25
17
|
import type { CasperConfig, CasperContext, CasperMemo } from "../types";
|
|
26
18
|
|
|
27
19
|
// The caller builds the {@link CasperContext} (config + logger) and passes it to each method (ADR-019).
|
|
28
|
-
|
|
20
|
+
//
|
|
21
|
+
// Casper supports everything the contract requires but `craftTransactionData`, so it declares
|
|
22
|
+
// the authoring type and omits its unsupported *capabilities* — block queries, `call`,
|
|
23
|
+
// `register`, staking and raw crafting — rather than stubbing each one. That distinction is
|
|
24
|
+
// the point: eight omissions are capabilities this chain does not expose, while the stub
|
|
25
|
+
// below is a required method this module does not implement, which the type will not let us
|
|
26
|
+
// omit and which therefore stays visible here.
|
|
27
|
+
export function createApi() {
|
|
29
28
|
return {
|
|
30
29
|
lastBlock,
|
|
31
|
-
getBlockInfo(_context: CasperContext, _height: number): Promise<BlockInfo> {
|
|
32
|
-
throw new Error("getBlockInfo is not supported");
|
|
33
|
-
},
|
|
34
|
-
getBlock(_context: CasperContext, _height: number): Promise<Block> {
|
|
35
|
-
throw new Error("getBlock is not supported");
|
|
36
|
-
},
|
|
37
|
-
async call() {
|
|
38
|
-
throw new Error("call is not supported");
|
|
39
|
-
},
|
|
40
|
-
async register() {
|
|
41
|
-
throw new Error("register is not supported");
|
|
42
|
-
},
|
|
43
|
-
getValidators(
|
|
44
|
-
_context: CasperContext,
|
|
45
|
-
_options?: { cursor?: Cursor },
|
|
46
|
-
): Promise<Page<Validator>> {
|
|
47
|
-
throw new Error("getValidators is not supported");
|
|
48
|
-
},
|
|
49
30
|
getBalance(
|
|
50
31
|
context: CasperContext,
|
|
51
32
|
address: string,
|
|
@@ -54,42 +35,17 @@ export function createApi(): CoinModuleApi<CasperConfig, CasperMemo> {
|
|
|
54
35
|
return rejectBalanceOptions(() => getAccountBalance(context, address), options);
|
|
55
36
|
},
|
|
56
37
|
listOperations,
|
|
57
|
-
|
|
58
|
-
_context: CasperContext,
|
|
59
|
-
_address: string,
|
|
60
|
-
_options?: { cursor?: Cursor },
|
|
61
|
-
): Promise<Page<Stake>> {
|
|
62
|
-
throw new Error("getStakes is not supported");
|
|
63
|
-
},
|
|
64
|
-
getRewards(
|
|
65
|
-
_context: CasperContext,
|
|
66
|
-
_address: string,
|
|
67
|
-
_options?: { cursor?: Cursor },
|
|
68
|
-
): Promise<Page<Reward>> {
|
|
69
|
-
throw new Error("getRewards is not supported");
|
|
70
|
-
},
|
|
71
|
-
craftTransaction: (_context, transactionIntent, options) =>
|
|
38
|
+
craftTransaction: (_context, transactionIntent, options?) =>
|
|
72
39
|
craftTransaction(transactionIntent, options?.customFees),
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
_transaction: string,
|
|
76
|
-
_sender: string,
|
|
77
|
-
_publicKey: string,
|
|
78
|
-
_sequence: bigint,
|
|
79
|
-
): Promise<CraftedTransaction> {
|
|
80
|
-
throw new Error("craftRawTransaction is not supported");
|
|
81
|
-
},
|
|
82
|
-
combine: (_context, tx, signature, options) => combine(tx, signature, options?.pubkey),
|
|
83
|
-
broadcast: (context, tx) => broadcast(context, tx),
|
|
40
|
+
combine: (_context, tx, signature, options?) => combine(tx, signature, options?.pubkey),
|
|
41
|
+
broadcast: (context, tx, _options?) => broadcast(context, tx),
|
|
84
42
|
estimateFees,
|
|
85
|
-
validateIntent: async (_context, intent, balances, options) =>
|
|
43
|
+
validateIntent: async (_context, intent, balances, options?) =>
|
|
86
44
|
validateIntent(intent, balances, options?.customFees),
|
|
87
45
|
// Casper uses (transaction hash + TTL) for replay protection rather than a
|
|
88
46
|
// per-account nonce, so getNextSequence has no meaningful value here.
|
|
89
47
|
getNextSequence: async (_context: CasperContext, _address: string) => 0n,
|
|
90
48
|
validateAddress: (_context, address, parameters) => validateAddress(address, parameters),
|
|
91
|
-
craftTransactionData
|
|
92
|
-
|
|
93
|
-
},
|
|
94
|
-
};
|
|
49
|
+
craftTransactionData: notSupported("craftTransactionData"),
|
|
50
|
+
} satisfies CoinModuleImpl<CasperConfig, CasperMemo>;
|
|
95
51
|
}
|
|
@@ -50,6 +50,22 @@ describe("craftTransaction", () => {
|
|
|
50
50
|
}),
|
|
51
51
|
);
|
|
52
52
|
|
|
53
|
+
expect(idSpy).toHaveBeenCalledTimes(1);
|
|
54
|
+
expect(idSpy).toHaveBeenCalledWith(TEST_TRANSFER_IDS.VALID);
|
|
55
|
+
const idArg = getArgs(transaction).getByName("id");
|
|
56
|
+
expect(idArg?.option?.isEmpty()).toBe(false);
|
|
57
|
+
expect(idArg?.option?.value()?.ui64?.toString()).toBe(TEST_TRANSFER_IDS.VALID);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("includes the transfer id from the generic-adapter memo shape (type=transferId)", async () => {
|
|
61
|
+
const idSpy = jest.spyOn(NativeTransferBuilder.prototype, "id");
|
|
62
|
+
|
|
63
|
+
const { transaction } = await craftTransaction({
|
|
64
|
+
...baseIntent(),
|
|
65
|
+
memo: { type: "transferId", value: TEST_TRANSFER_IDS.VALID },
|
|
66
|
+
} as TransactionIntent<CasperMemo>);
|
|
67
|
+
|
|
68
|
+
expect(idSpy).toHaveBeenCalledTimes(1);
|
|
53
69
|
expect(idSpy).toHaveBeenCalledWith(TEST_TRANSFER_IDS.VALID);
|
|
54
70
|
const idArg = getArgs(transaction).getByName("id");
|
|
55
71
|
expect(idArg?.option?.isEmpty()).toBe(false);
|
|
@@ -134,6 +150,7 @@ describe("craftTransaction", () => {
|
|
|
134
150
|
|
|
135
151
|
await craftTransaction(baseIntent(), { value: 999_000_000n });
|
|
136
152
|
|
|
153
|
+
expect(paymentSpy).toHaveBeenCalledTimes(1);
|
|
137
154
|
expect(paymentSpy).toHaveBeenCalledWith(999_000_000);
|
|
138
155
|
});
|
|
139
156
|
|
|
@@ -142,6 +159,7 @@ describe("craftTransaction", () => {
|
|
|
142
159
|
|
|
143
160
|
await craftTransaction(baseIntent());
|
|
144
161
|
|
|
162
|
+
expect(paymentSpy).toHaveBeenCalledTimes(1);
|
|
145
163
|
expect(paymentSpy).toHaveBeenCalledWith(CASPER_FEES_MOTES);
|
|
146
164
|
});
|
|
147
165
|
});
|
|
@@ -10,7 +10,7 @@ import { CASPER_DEFAULT_TTL, CASPER_MAX_TRANSFER_ID, CASPER_NETWORK } from "../c
|
|
|
10
10
|
import { CasperInvalidTransferId } from "../errors";
|
|
11
11
|
import type { CasperMemo } from "../types";
|
|
12
12
|
import { getEstimatedFees } from "./estimateFees";
|
|
13
|
-
import { toSafeNumber } from "./utils";
|
|
13
|
+
import { getTransferIdFromMemo, toSafeNumber } from "./utils";
|
|
14
14
|
import { isAddressValid } from "./validateAddress";
|
|
15
15
|
import { validateMemo } from "./validateMemo";
|
|
16
16
|
|
|
@@ -35,8 +35,9 @@ export async function craftTransaction(
|
|
|
35
35
|
throw new InvalidAddress(`Invalid recipient Address ${recipient}`);
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
const
|
|
39
|
-
|
|
38
|
+
const transferId = getTransferIdFromMemo(
|
|
39
|
+
"memo" in transactionIntent ? transactionIntent.memo : undefined,
|
|
40
|
+
);
|
|
40
41
|
|
|
41
42
|
if (typeof transferId === "string" && transferId.length > 0 && !validateMemo(transferId)) {
|
|
42
43
|
throw new CasperInvalidTransferId("", {
|
package/src/logic/utils.test.ts
CHANGED
|
@@ -5,7 +5,9 @@ import {
|
|
|
5
5
|
methodToString,
|
|
6
6
|
getRandomTransferID,
|
|
7
7
|
toSafeNumber,
|
|
8
|
+
getTransferIdFromMemo,
|
|
8
9
|
} from "./utils";
|
|
10
|
+
import type { CasperMemo } from "../types";
|
|
9
11
|
|
|
10
12
|
describe("Casper utils", () => {
|
|
11
13
|
describe("isNoErrorReturnCode", () => {
|
|
@@ -92,4 +94,23 @@ describe("Casper utils", () => {
|
|
|
92
94
|
expect(() => toSafeNumber(BigInt(Number.MIN_SAFE_INTEGER) - 1n)).toThrow(RangeError);
|
|
93
95
|
});
|
|
94
96
|
});
|
|
97
|
+
|
|
98
|
+
describe("getTransferIdFromMemo", () => {
|
|
99
|
+
it.each([
|
|
100
|
+
["undefined memo", undefined, undefined],
|
|
101
|
+
["MemoNotSupported", { type: "none" } as CasperMemo, undefined],
|
|
102
|
+
[
|
|
103
|
+
"StringMemo<'transferId'>",
|
|
104
|
+
{ type: "string", kind: "transferId", value: "12345" } as CasperMemo,
|
|
105
|
+
"12345",
|
|
106
|
+
],
|
|
107
|
+
[
|
|
108
|
+
"generic-adapter memo { type: 'transferId' }",
|
|
109
|
+
{ type: "transferId", value: "9007199254740993" } as CasperMemo,
|
|
110
|
+
"9007199254740993",
|
|
111
|
+
],
|
|
112
|
+
])("returns correct transferId for %s", (_desc, memo, expected) => {
|
|
113
|
+
expect(getTransferIdFromMemo(memo)).toBe(expected);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
95
116
|
});
|
package/src/logic/utils.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import BigNumber from "bignumber.js";
|
|
2
|
+
import type { CasperMemo } from "../types";
|
|
2
3
|
|
|
3
4
|
const validHexRegExp = new RegExp(/[0-9A-Fa-f]{6}/g);
|
|
4
5
|
const validBase64RegExp = new RegExp(
|
|
@@ -55,3 +56,11 @@ export function toSafeNumber(value: bigint): number {
|
|
|
55
56
|
|
|
56
57
|
return Number(value);
|
|
57
58
|
}
|
|
59
|
+
|
|
60
|
+
// Two memo shapes coexist until LIVE-35735 unifies them.
|
|
61
|
+
export function getTransferIdFromMemo(memo: CasperMemo | undefined): string | undefined {
|
|
62
|
+
if (!memo) return undefined;
|
|
63
|
+
if (memo.type === "string" && memo.kind === "transferId") return memo.value;
|
|
64
|
+
if (memo.type === "transferId") return memo.value;
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
@@ -135,6 +135,32 @@ describe("validateIntent", () => {
|
|
|
135
135
|
expect(errors.transaction).toBeInstanceOf(CasperInvalidTransferId);
|
|
136
136
|
});
|
|
137
137
|
|
|
138
|
+
describe("framework memo shape { type: 'transferId' }", () => {
|
|
139
|
+
it("accepts a valid transfer id", () => {
|
|
140
|
+
const intent: TransactionIntent<CasperMemo> = {
|
|
141
|
+
...buildIntent(sendCase()),
|
|
142
|
+
memo: { type: "transferId", value: "42" },
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
const { errors } = validateIntent(intent, buildBalances(sendCase()), { value: FEES });
|
|
146
|
+
|
|
147
|
+
expect(errors.sender).toBeUndefined();
|
|
148
|
+
expect(errors.transaction).toBeUndefined();
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
it("rejects an out-of-range transfer id", () => {
|
|
152
|
+
const intent: TransactionIntent<CasperMemo> = {
|
|
153
|
+
...buildIntent(sendCase()),
|
|
154
|
+
memo: { type: "transferId", value: OUT_OF_RANGE_TRANSFER_ID },
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const { errors } = validateIntent(intent, buildBalances(sendCase()), { value: FEES });
|
|
158
|
+
|
|
159
|
+
expect(errors.sender).toBeInstanceOf(CasperInvalidTransferId);
|
|
160
|
+
expect(errors.transaction).toBeInstanceOf(CasperInvalidTransferId);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
138
164
|
it("reduces the accepted useAllAmount by the locked funds", () => {
|
|
139
165
|
const locked = 10_000_000_000n;
|
|
140
166
|
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
} from "../constants";
|
|
21
21
|
import { CasperInvalidTransferId } from "../errors";
|
|
22
22
|
import type { CasperMemo } from "../types";
|
|
23
|
+
import { getTransferIdFromMemo } from "./utils";
|
|
23
24
|
import { isAddressValid } from "./validateAddress";
|
|
24
25
|
import { validateMemo } from "./validateMemo";
|
|
25
26
|
|
|
@@ -109,8 +110,7 @@ export function validateIntent(
|
|
|
109
110
|
const balance = nativeBalance?.value ?? 0n;
|
|
110
111
|
const spendableBalance = balance - (nativeBalance?.locked ?? 0n);
|
|
111
112
|
|
|
112
|
-
const
|
|
113
|
-
const transferId = memo?.type === "string" && memo.kind === "transferId" ? memo.value : undefined;
|
|
113
|
+
const transferId = getTransferIdFromMemo("memo" in intent ? intent.memo : undefined);
|
|
114
114
|
|
|
115
115
|
validateRecipient(recipient, sender, currencyName, errors);
|
|
116
116
|
validateSender(sender, transferId, currencyName, errors);
|
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
import { MemoNotSupported, StringMemo } from "@ledgerhq/coin-module-framework/api/types";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// TODO: remove after LIVE-35735 — generic adapter will produce StringMemo<"transferId"> directly
|
|
4
|
+
export interface FrameworkTransferIdMemo {
|
|
5
|
+
type: "transferId";
|
|
6
|
+
value: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type CasperMemo = MemoNotSupported | StringMemo<"transferId"> | FrameworkTransferIdMemo;
|