@ledgerhq/coin-canton 0.5.0-nightly.1 → 0.5.0-nightly.3
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/.turbo/turbo-build.log +1 -1
- package/.unimportedrc.json +12 -4
- package/CHANGELOG.md +32 -0
- package/lib/api/getBalance.integ.test.js +1 -1
- package/lib/api/getBalance.integ.test.js.map +1 -1
- package/lib/api/index.d.ts.map +1 -1
- package/lib/api/index.js +11 -8
- package/lib/api/index.js.map +1 -1
- package/lib/bridge/broadcast.d.ts.map +1 -1
- package/lib/bridge/broadcast.js +2 -1
- package/lib/bridge/broadcast.js.map +1 -1
- package/lib/bridge/createTransaction.test.js +1 -1
- package/lib/bridge/createTransaction.test.js.map +1 -1
- package/lib/bridge/index.d.ts +3 -3
- package/lib/bridge/index.d.ts.map +1 -1
- package/lib/bridge/index.js +9 -1
- package/lib/bridge/index.js.map +1 -1
- package/lib/bridge/onboard.d.ts +10 -0
- package/lib/bridge/onboard.d.ts.map +1 -0
- package/lib/bridge/onboard.integ.test.d.ts +2 -0
- package/lib/bridge/onboard.integ.test.d.ts.map +1 -0
- package/lib/bridge/onboard.integ.test.js +156 -0
- package/lib/bridge/onboard.integ.test.js.map +1 -0
- package/lib/bridge/onboard.js +139 -0
- package/lib/bridge/onboard.js.map +1 -0
- package/lib/bridge/prepareTransaction.d.ts.map +1 -1
- package/lib/bridge/prepareTransaction.js +5 -7
- package/lib/bridge/prepareTransaction.js.map +1 -1
- package/lib/bridge/signOperation.d.ts.map +1 -1
- package/lib/bridge/signOperation.js +7 -9
- package/lib/bridge/signOperation.js.map +1 -1
- package/lib/bridge/sync.d.ts.map +1 -1
- package/lib/bridge/sync.integ.test.d.ts +2 -0
- package/lib/bridge/sync.integ.test.d.ts.map +1 -0
- package/lib/bridge/sync.integ.test.js +175 -0
- package/lib/bridge/sync.integ.test.js.map +1 -0
- package/lib/bridge/sync.js +40 -36
- package/lib/bridge/sync.js.map +1 -1
- package/lib/bridge/updateTransaction.d.ts.map +1 -1
- package/lib/bridge/updateTransaction.js +0 -4
- package/lib/bridge/updateTransaction.js.map +1 -1
- package/lib/common-logic/history/listOperations.d.ts.map +1 -1
- package/lib/common-logic/history/listOperations.js +19 -31
- package/lib/common-logic/history/listOperations.js.map +1 -1
- package/lib/common-logic/transaction/broadcast.d.ts.map +1 -1
- package/lib/common-logic/transaction/broadcast.js +2 -1
- package/lib/common-logic/transaction/broadcast.js.map +1 -1
- package/lib/common-logic/transaction/broadcast.test.js +3 -3
- package/lib/common-logic/transaction/broadcast.test.js.map +1 -1
- package/lib/common-logic/transaction/combine.d.ts +1 -1
- package/lib/common-logic/transaction/combine.d.ts.map +1 -1
- package/lib/common-logic/transaction/combine.js +2 -3
- package/lib/common-logic/transaction/combine.js.map +1 -1
- package/lib/common-logic/transaction/combine.test.js +3 -13
- package/lib/common-logic/transaction/combine.test.js.map +1 -1
- package/lib/common-logic/transaction/craftTransaction.d.ts +5 -3
- package/lib/common-logic/transaction/craftTransaction.d.ts.map +1 -1
- package/lib/common-logic/transaction/craftTransaction.js +11 -12
- package/lib/common-logic/transaction/craftTransaction.js.map +1 -1
- package/lib/network/gateway.d.ts +196 -5
- package/lib/network/gateway.d.ts.map +1 -1
- package/lib/network/gateway.integ.test.js +121 -11
- package/lib/network/gateway.integ.test.js.map +1 -1
- package/lib/network/gateway.js +99 -21
- package/lib/network/gateway.js.map +1 -1
- package/lib/network/node.d.ts +2 -2
- package/lib/network/node.d.ts.map +1 -1
- package/lib/network/node.js.map +1 -1
- package/lib/network/types.d.ts +1 -1
- package/lib/network/types.d.ts.map +1 -1
- package/lib/signer/getAddress.d.ts.map +1 -1
- package/lib/signer/getAddress.js +2 -2
- package/lib/signer/getAddress.js.map +1 -1
- package/lib/test/cantonTestUtils.d.ts +33 -0
- package/lib/test/cantonTestUtils.d.ts.map +1 -0
- package/lib/test/cantonTestUtils.js +159 -0
- package/lib/test/cantonTestUtils.js.map +1 -0
- package/lib/types/bridge.d.ts +7 -1
- package/lib/types/bridge.d.ts.map +1 -1
- package/lib/types/index.d.ts +1 -10
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +1 -0
- package/lib/types/index.js.map +1 -1
- package/lib/types/onboard.d.ts +55 -0
- package/lib/types/onboard.d.ts.map +1 -0
- package/lib/types/onboard.js +22 -0
- package/lib/types/onboard.js.map +1 -0
- package/lib-es/api/getBalance.integ.test.js +1 -1
- package/lib-es/api/getBalance.integ.test.js.map +1 -1
- package/lib-es/api/index.d.ts.map +1 -1
- package/lib-es/api/index.js +12 -9
- package/lib-es/api/index.js.map +1 -1
- package/lib-es/bridge/broadcast.d.ts.map +1 -1
- package/lib-es/bridge/broadcast.js +2 -1
- package/lib-es/bridge/broadcast.js.map +1 -1
- package/lib-es/bridge/createTransaction.test.js +1 -1
- package/lib-es/bridge/createTransaction.test.js.map +1 -1
- package/lib-es/bridge/index.d.ts +3 -3
- package/lib-es/bridge/index.d.ts.map +1 -1
- package/lib-es/bridge/index.js +9 -1
- package/lib-es/bridge/index.js.map +1 -1
- package/lib-es/bridge/onboard.d.ts +10 -0
- package/lib-es/bridge/onboard.d.ts.map +1 -0
- package/lib-es/bridge/onboard.integ.test.d.ts +2 -0
- package/lib-es/bridge/onboard.integ.test.d.ts.map +1 -0
- package/lib-es/bridge/onboard.integ.test.js +151 -0
- package/lib-es/bridge/onboard.integ.test.js.map +1 -0
- package/lib-es/bridge/onboard.js +133 -0
- package/lib-es/bridge/onboard.js.map +1 -0
- package/lib-es/bridge/prepareTransaction.d.ts.map +1 -1
- package/lib-es/bridge/prepareTransaction.js +6 -8
- package/lib-es/bridge/prepareTransaction.js.map +1 -1
- package/lib-es/bridge/signOperation.d.ts.map +1 -1
- package/lib-es/bridge/signOperation.js +8 -10
- package/lib-es/bridge/signOperation.js.map +1 -1
- package/lib-es/bridge/sync.d.ts.map +1 -1
- package/lib-es/bridge/sync.integ.test.d.ts +2 -0
- package/lib-es/bridge/sync.integ.test.d.ts.map +1 -0
- package/lib-es/bridge/sync.integ.test.js +137 -0
- package/lib-es/bridge/sync.integ.test.js.map +1 -0
- package/lib-es/bridge/sync.js +39 -35
- package/lib-es/bridge/sync.js.map +1 -1
- package/lib-es/bridge/updateTransaction.d.ts.map +1 -1
- package/lib-es/bridge/updateTransaction.js +0 -4
- package/lib-es/bridge/updateTransaction.js.map +1 -1
- package/lib-es/common-logic/history/listOperations.d.ts.map +1 -1
- package/lib-es/common-logic/history/listOperations.js +20 -29
- package/lib-es/common-logic/history/listOperations.js.map +1 -1
- package/lib-es/common-logic/transaction/broadcast.d.ts.map +1 -1
- package/lib-es/common-logic/transaction/broadcast.js +2 -1
- package/lib-es/common-logic/transaction/broadcast.js.map +1 -1
- package/lib-es/common-logic/transaction/broadcast.test.js +3 -3
- package/lib-es/common-logic/transaction/broadcast.test.js.map +1 -1
- package/lib-es/common-logic/transaction/combine.d.ts +1 -1
- package/lib-es/common-logic/transaction/combine.d.ts.map +1 -1
- package/lib-es/common-logic/transaction/combine.js +2 -3
- package/lib-es/common-logic/transaction/combine.js.map +1 -1
- package/lib-es/common-logic/transaction/combine.test.js +3 -13
- package/lib-es/common-logic/transaction/combine.test.js.map +1 -1
- package/lib-es/common-logic/transaction/craftTransaction.d.ts +5 -3
- package/lib-es/common-logic/transaction/craftTransaction.d.ts.map +1 -1
- package/lib-es/common-logic/transaction/craftTransaction.js +11 -12
- package/lib-es/common-logic/transaction/craftTransaction.js.map +1 -1
- package/lib-es/network/gateway.d.ts +196 -5
- package/lib-es/network/gateway.d.ts.map +1 -1
- package/lib-es/network/gateway.integ.test.js +122 -12
- package/lib-es/network/gateway.integ.test.js.map +1 -1
- package/lib-es/network/gateway.js +93 -20
- package/lib-es/network/gateway.js.map +1 -1
- package/lib-es/network/node.d.ts +2 -2
- package/lib-es/network/node.d.ts.map +1 -1
- package/lib-es/network/node.js.map +1 -1
- package/lib-es/network/types.d.ts +1 -1
- package/lib-es/network/types.d.ts.map +1 -1
- package/lib-es/signer/getAddress.d.ts.map +1 -1
- package/lib-es/signer/getAddress.js +2 -2
- package/lib-es/signer/getAddress.js.map +1 -1
- package/lib-es/test/cantonTestUtils.d.ts +33 -0
- package/lib-es/test/cantonTestUtils.d.ts.map +1 -0
- package/lib-es/test/cantonTestUtils.js +151 -0
- package/lib-es/test/cantonTestUtils.js.map +1 -0
- package/lib-es/types/bridge.d.ts +7 -1
- package/lib-es/types/bridge.d.ts.map +1 -1
- package/lib-es/types/index.d.ts +1 -10
- package/lib-es/types/index.d.ts.map +1 -1
- package/lib-es/types/index.js +1 -0
- package/lib-es/types/index.js.map +1 -1
- package/lib-es/types/onboard.d.ts +55 -0
- package/lib-es/types/onboard.d.ts.map +1 -0
- package/lib-es/types/onboard.js +19 -0
- package/lib-es/types/onboard.js.map +1 -0
- package/package.json +7 -7
- package/src/api/getBalance.integ.test.ts +1 -2
- package/src/api/index.ts +33 -26
- package/src/bridge/broadcast.ts +2 -3
- package/src/bridge/createTransaction.test.ts +1 -1
- package/src/bridge/index.ts +14 -4
- package/src/bridge/onboard.integ.test.ts +219 -0
- package/src/bridge/onboard.ts +220 -0
- package/src/bridge/prepareTransaction.ts +6 -15
- package/src/bridge/signOperation.ts +9 -16
- package/src/bridge/sync.integ.test.ts +180 -0
- package/src/bridge/sync.ts +61 -49
- package/src/bridge/updateTransaction.ts +0 -5
- package/src/common-logic/history/listOperations.ts +20 -31
- package/src/common-logic/transaction/broadcast.test.ts +3 -3
- package/src/common-logic/transaction/broadcast.ts +2 -1
- package/src/common-logic/transaction/combine.test.ts +3 -13
- package/src/common-logic/transaction/combine.ts +2 -4
- package/src/common-logic/transaction/craftTransaction.ts +15 -17
- package/src/network/gateway.integ.test.ts +156 -17
- package/src/network/gateway.ts +337 -30
- package/src/network/node.ts +3 -3
- package/src/network/types.ts +1 -1
- package/src/signer/getAddress.ts +3 -5
- package/src/test/cantonTestUtils.ts +181 -0
- package/src/types/bridge.ts +20 -0
- package/src/types/index.ts +1 -11
- package/src/types/onboard.ts +65 -0
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import BigNumber from "bignumber.js";
|
|
2
|
+
import { AccountShapeInfo } from "@ledgerhq/coin-framework/bridge/jsHelpers";
|
|
3
|
+
import {
|
|
4
|
+
getDerivationModesForCurrency,
|
|
5
|
+
getDerivationScheme,
|
|
6
|
+
runDerivationScheme,
|
|
7
|
+
} from "@ledgerhq/coin-framework/derivation";
|
|
8
|
+
import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/currencies";
|
|
9
|
+
import { Account, Operation } from "@ledgerhq/types-live";
|
|
10
|
+
import coinConfig from "../config";
|
|
11
|
+
import * as gateway from "../network/gateway";
|
|
12
|
+
import { getAccountShape } from "./sync";
|
|
13
|
+
|
|
14
|
+
const TEST_ADDRESS =
|
|
15
|
+
"b6400f93ea1c74aea86be39b0ccc846fc5de01f12b2ad0d7c31848d6fb6eb6d9::1220c81315e2bf2524a9141bcc6cbf19b61c151e0dcaa95343c0ccf53aed7415c4ec";
|
|
16
|
+
const currency = getCryptoCurrencyById("canton_network");
|
|
17
|
+
const derivationMode = getDerivationModesForCurrency(currency)[0];
|
|
18
|
+
const derivationPath = runDerivationScheme(
|
|
19
|
+
getDerivationScheme({ derivationMode, currency }),
|
|
20
|
+
currency,
|
|
21
|
+
{
|
|
22
|
+
account: 0,
|
|
23
|
+
},
|
|
24
|
+
);
|
|
25
|
+
const ACCOUNT_SHAPE_INFO: AccountShapeInfo = {
|
|
26
|
+
address: TEST_ADDRESS,
|
|
27
|
+
currency,
|
|
28
|
+
derivationMode,
|
|
29
|
+
derivationPath,
|
|
30
|
+
index: 0,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
describe("sync (devnet)", () => {
|
|
34
|
+
beforeAll(async () => {
|
|
35
|
+
coinConfig.setCoinConfig(() => ({
|
|
36
|
+
gatewayUrl: "https://canton-gateway.api.live.ledger-test.com",
|
|
37
|
+
useGateway: true,
|
|
38
|
+
networkType: "devnet",
|
|
39
|
+
status: {
|
|
40
|
+
type: "active",
|
|
41
|
+
},
|
|
42
|
+
}));
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("getAccountShape", () => {
|
|
46
|
+
it("should fetch account shape for a valid address", async () => {
|
|
47
|
+
const result = await getAccountShape(ACCOUNT_SHAPE_INFO, { paginationConfig: {} });
|
|
48
|
+
|
|
49
|
+
expect(result).toBeDefined();
|
|
50
|
+
expect(result.id).toBeDefined();
|
|
51
|
+
expect(result.xpub).toBe(TEST_ADDRESS.replace(/:/g, "_"));
|
|
52
|
+
expect(result.blockHeight).toBeGreaterThan(0);
|
|
53
|
+
expect(result.balance).toBeDefined();
|
|
54
|
+
expect(result.spendableBalance).toBeDefined();
|
|
55
|
+
expect(result.operations).toBeDefined();
|
|
56
|
+
expect(result.operationsCount).toBeGreaterThanOrEqual(0);
|
|
57
|
+
|
|
58
|
+
expect(result.balance).toBeInstanceOf(Object);
|
|
59
|
+
expect(result.balance?.toNumber).toBeDefined();
|
|
60
|
+
expect(result.spendableBalance).toBeInstanceOf(Object);
|
|
61
|
+
expect(result.spendableBalance?.toNumber).toBeDefined();
|
|
62
|
+
|
|
63
|
+
expect(result.spendableBalance?.toNumber()).toBeLessThanOrEqual(
|
|
64
|
+
result.balance?.toNumber() || 0,
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("should handle address with colons correctly", async () => {
|
|
69
|
+
const result = await getAccountShape(ACCOUNT_SHAPE_INFO, { paginationConfig: {} });
|
|
70
|
+
|
|
71
|
+
expect(result.xpub).toBe(TEST_ADDRESS.replace(/:/g, "_"));
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("should merge operations correctly with initial account", async () => {
|
|
75
|
+
const operations: Operation[] = [
|
|
76
|
+
{
|
|
77
|
+
id: "test-op-1",
|
|
78
|
+
hash: "test-hash-1",
|
|
79
|
+
accountId: "test-account",
|
|
80
|
+
type: "OUT" as const,
|
|
81
|
+
value: new BigNumber(1000000),
|
|
82
|
+
fee: new BigNumber(100000),
|
|
83
|
+
blockHash: "block-hash-1",
|
|
84
|
+
blockHeight: 100,
|
|
85
|
+
senders: [TEST_ADDRESS],
|
|
86
|
+
recipients: ["recipient-1"],
|
|
87
|
+
date: new Date("2023-01-01"),
|
|
88
|
+
transactionSequenceNumber: 100,
|
|
89
|
+
extra: { uid: "uid-1" },
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
const result = await getAccountShape(
|
|
94
|
+
{
|
|
95
|
+
...ACCOUNT_SHAPE_INFO,
|
|
96
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
97
|
+
initialAccount: { operations } as Account,
|
|
98
|
+
},
|
|
99
|
+
{ paginationConfig: {} },
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
expect(result.operations).toBeDefined();
|
|
103
|
+
expect(result.operationsCount).toBeGreaterThanOrEqual(1);
|
|
104
|
+
const initialOp = result.operations?.find(op => op.id === "test-op-1");
|
|
105
|
+
expect(initialOp).toBeDefined();
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("should take locked balance into account when calculating spendable balance", async () => {
|
|
109
|
+
const mockGetBalance = jest.spyOn(gateway, "getBalance");
|
|
110
|
+
|
|
111
|
+
mockGetBalance.mockResolvedValue([
|
|
112
|
+
{
|
|
113
|
+
instrument_id: "canton_network",
|
|
114
|
+
amount: 1000000,
|
|
115
|
+
locked: true,
|
|
116
|
+
},
|
|
117
|
+
]);
|
|
118
|
+
|
|
119
|
+
const result = await getAccountShape(ACCOUNT_SHAPE_INFO, { paginationConfig: {} });
|
|
120
|
+
|
|
121
|
+
expect(result.balance?.toNumber()).toBe(1000000);
|
|
122
|
+
expect(result.spendableBalance?.toNumber()).toBe(0);
|
|
123
|
+
|
|
124
|
+
mockGetBalance.mockRestore();
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("should call getOperations with correct cursor based with initial account", async () => {
|
|
128
|
+
const mockGetOperations = jest.spyOn(gateway, "getOperations");
|
|
129
|
+
const operation: Operation = {
|
|
130
|
+
id: "test-op-1",
|
|
131
|
+
hash: "test-hash-1",
|
|
132
|
+
accountId: "test-account",
|
|
133
|
+
type: "OUT" as const,
|
|
134
|
+
value: new BigNumber(1000000),
|
|
135
|
+
fee: new BigNumber(100000),
|
|
136
|
+
blockHash: "block-hash-1",
|
|
137
|
+
blockHeight: 100,
|
|
138
|
+
senders: [TEST_ADDRESS],
|
|
139
|
+
recipients: ["recipient-1"],
|
|
140
|
+
date: new Date("2023-01-01"),
|
|
141
|
+
transactionSequenceNumber: 100,
|
|
142
|
+
extra: { uid: "uid-1" },
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
146
|
+
const initialAccount = { operations: [operation] } as Account;
|
|
147
|
+
|
|
148
|
+
const result = await getAccountShape(
|
|
149
|
+
{
|
|
150
|
+
...ACCOUNT_SHAPE_INFO,
|
|
151
|
+
initialAccount,
|
|
152
|
+
},
|
|
153
|
+
{ paginationConfig: {} },
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
expect(mockGetOperations).toHaveBeenCalledWith(TEST_ADDRESS, {
|
|
157
|
+
cursor: (operation.blockHeight || 0) + 1,
|
|
158
|
+
limit: 100,
|
|
159
|
+
});
|
|
160
|
+
expect(result.operations).toBeDefined();
|
|
161
|
+
expect(result.operationsCount).toBeGreaterThan(1);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
it("should call getOperations with cursor 0 when no initial account", async () => {
|
|
165
|
+
const mockGetOperations = jest.spyOn(gateway, "getOperations");
|
|
166
|
+
|
|
167
|
+
const result = await getAccountShape(ACCOUNT_SHAPE_INFO, { paginationConfig: {} });
|
|
168
|
+
|
|
169
|
+
expect(result.operations).toBeDefined();
|
|
170
|
+
expect(result.operationsCount).toBeGreaterThan(1);
|
|
171
|
+
|
|
172
|
+
expect(mockGetOperations).toHaveBeenCalledWith(TEST_ADDRESS, {
|
|
173
|
+
cursor: 0,
|
|
174
|
+
limit: 100,
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
mockGetOperations.mockRestore();
|
|
178
|
+
});
|
|
179
|
+
});
|
|
180
|
+
});
|
package/src/bridge/sync.ts
CHANGED
|
@@ -2,101 +2,113 @@ import BigNumber from "bignumber.js";
|
|
|
2
2
|
import { Operation } from "@ledgerhq/types-live";
|
|
3
3
|
import { encodeAccountId } from "@ledgerhq/coin-framework/account/index";
|
|
4
4
|
import { GetAccountShape, mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers";
|
|
5
|
-
import {
|
|
6
|
-
import { getAccountInfo, getLedgerEnd } from "../network/node";
|
|
5
|
+
import { getBalance, getLedgerEnd, getOperations, type OperationInfo } from "../network/gateway";
|
|
7
6
|
|
|
8
7
|
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
|
|
9
|
-
import { BoilerplateOperation } from "../network/types";
|
|
10
8
|
import coinConfig from "../config";
|
|
11
9
|
|
|
12
|
-
const
|
|
10
|
+
const txInfoToOperationAdapter =
|
|
13
11
|
(accountId: string, address: string) =>
|
|
14
|
-
({
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
}
|
|
12
|
+
(txInfo: OperationInfo): Operation => {
|
|
13
|
+
const {
|
|
14
|
+
transaction_hash,
|
|
15
|
+
uid,
|
|
16
|
+
block: { height, hash },
|
|
17
|
+
senders,
|
|
18
|
+
recipients,
|
|
19
|
+
transaction_timestamp,
|
|
20
|
+
fee: { value: fee },
|
|
21
|
+
transfers: [{ value: transferValue }],
|
|
22
|
+
} = txInfo;
|
|
23
|
+
const type = senders.includes(address) ? "OUT" : "IN";
|
|
24
|
+
const value = new BigNumber(transferValue);
|
|
25
|
+
const feeValue = new BigNumber(fee);
|
|
30
26
|
|
|
31
27
|
const op: Operation = {
|
|
32
|
-
id: encodeOperationId(accountId,
|
|
33
|
-
hash:
|
|
28
|
+
id: encodeOperationId(accountId, transaction_hash, type),
|
|
29
|
+
hash: transaction_hash,
|
|
34
30
|
accountId,
|
|
35
31
|
type,
|
|
36
32
|
value,
|
|
37
33
|
fee: feeValue,
|
|
38
|
-
blockHash:
|
|
39
|
-
blockHeight:
|
|
40
|
-
senders
|
|
41
|
-
recipients
|
|
42
|
-
date: new Date(),
|
|
43
|
-
transactionSequenceNumber:
|
|
44
|
-
extra: {
|
|
34
|
+
blockHash: hash,
|
|
35
|
+
blockHeight: height,
|
|
36
|
+
senders,
|
|
37
|
+
recipients,
|
|
38
|
+
date: new Date(transaction_timestamp),
|
|
39
|
+
transactionSequenceNumber: height,
|
|
40
|
+
extra: {
|
|
41
|
+
uid,
|
|
42
|
+
},
|
|
45
43
|
};
|
|
46
44
|
|
|
47
45
|
return op;
|
|
48
46
|
};
|
|
49
47
|
|
|
50
48
|
const filterOperations = (
|
|
51
|
-
transactions:
|
|
49
|
+
transactions: OperationInfo[],
|
|
52
50
|
accountId: string,
|
|
53
51
|
address: string,
|
|
54
|
-
) => {
|
|
52
|
+
): Operation[] => {
|
|
55
53
|
return transactions
|
|
56
|
-
.filter(
|
|
57
|
-
|
|
58
|
-
tx.TransactionType === "Payment" && typeof meta.delivered_amount === "string",
|
|
59
|
-
)
|
|
60
|
-
.map(operationAdapter(accountId, address))
|
|
61
|
-
.filter((op): op is Operation => Boolean(op));
|
|
54
|
+
.filter(tx => tx.type === "Receive" || tx.type === "Send")
|
|
55
|
+
.map(txInfoToOperationAdapter(accountId, address));
|
|
62
56
|
};
|
|
63
57
|
|
|
64
58
|
export const getAccountShape: GetAccountShape = async info => {
|
|
65
59
|
const { address, initialAccount, currency, derivationMode } = info;
|
|
60
|
+
// TODO: we need better solution ?
|
|
61
|
+
const xpubOrAddress = address?.replace(/:/g, "_") || "";
|
|
66
62
|
|
|
67
63
|
const accountId = encodeAccountId({
|
|
68
64
|
type: "js",
|
|
69
65
|
version: "2",
|
|
70
66
|
currencyId: currency.id,
|
|
71
|
-
xpubOrAddress
|
|
72
|
-
derivationMode,
|
|
67
|
+
xpubOrAddress,
|
|
68
|
+
derivationMode: "",
|
|
73
69
|
});
|
|
74
70
|
|
|
75
71
|
// blockheight retrieval
|
|
76
72
|
const blockHeight = await getLedgerEnd();
|
|
77
73
|
|
|
78
74
|
// Account info retrieval + spendable balance calculation
|
|
79
|
-
const accountInfo = await getAccountInfo(address);
|
|
80
|
-
const
|
|
75
|
+
// const accountInfo = await getAccountInfo(address);
|
|
76
|
+
const balances = await getBalance(address);
|
|
77
|
+
|
|
78
|
+
// TODO change to balance.instrument_id === "Amulet" after update on backend
|
|
79
|
+
const balanceData = balances.find(balance => balance.instrument_id.includes("Amulet")) || {
|
|
80
|
+
instrument_id: "Amulet",
|
|
81
|
+
amount: 0,
|
|
82
|
+
locked: false,
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const balance = new BigNumber(balanceData.amount);
|
|
81
86
|
const reserveMin = coinConfig.getCoinConfig().minReserve || 0;
|
|
82
|
-
const
|
|
83
|
-
|
|
87
|
+
const lockedAmount = balanceData.locked ? balance : new BigNumber(0);
|
|
88
|
+
const spendableBalance = BigNumber.max(
|
|
89
|
+
0,
|
|
90
|
+
balance.minus(lockedAmount).minus(BigNumber(reserveMin)),
|
|
84
91
|
);
|
|
85
92
|
|
|
86
93
|
// Tx history fetching
|
|
87
94
|
const oldOperations = initialAccount?.operations || [];
|
|
88
95
|
const startAt = oldOperations.length ? (oldOperations[0].blockHeight || 0) + 1 : 0;
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
96
|
+
const transactionData = await getOperations(address, {
|
|
97
|
+
cursor: startAt,
|
|
98
|
+
limit: 100,
|
|
92
99
|
});
|
|
93
|
-
|
|
94
|
-
const
|
|
100
|
+
|
|
101
|
+
const newOperations = filterOperations(
|
|
102
|
+
transactionData.operations,
|
|
103
|
+
accountId,
|
|
104
|
+
address.replace(/_/g, ":"),
|
|
105
|
+
);
|
|
106
|
+
const operations = mergeOps(oldOperations, newOperations);
|
|
95
107
|
|
|
96
108
|
// We return the new account shape
|
|
97
109
|
const shape = {
|
|
98
110
|
id: accountId,
|
|
99
|
-
xpub:
|
|
111
|
+
xpub: xpubOrAddress,
|
|
100
112
|
blockHeight,
|
|
101
113
|
balance,
|
|
102
114
|
spendableBalance,
|
|
@@ -8,10 +8,5 @@ import type { Transaction } from "../types";
|
|
|
8
8
|
// NOTE: here is an example transaction updater function
|
|
9
9
|
// in this case, it resets fee to null depending on the patch content
|
|
10
10
|
export const updateTransaction: AccountBridge<Transaction>["updateTransaction"] = (tx, patch) => {
|
|
11
|
-
// eslint-disable-next-line no-constant-condition
|
|
12
|
-
if (patch.recipient === "boilerplate1" || true) {
|
|
13
|
-
patch = { ...patch, fee: null };
|
|
14
|
-
}
|
|
15
|
-
|
|
16
11
|
return defaultUpdateTransaction(tx, patch);
|
|
17
12
|
};
|
|
@@ -1,12 +1,7 @@
|
|
|
1
1
|
import type { Operation, Pagination } from "@ledgerhq/coin-framework/api/index";
|
|
2
|
-
import {
|
|
2
|
+
import { getOperations } from "../../network/gateway";
|
|
3
3
|
import coinConfig from "../../config";
|
|
4
4
|
|
|
5
|
-
const getNativeContractId = () =>
|
|
6
|
-
coinConfig.getCoinConfig().nativeInstrumentId !== undefined
|
|
7
|
-
? coinConfig.getCoinConfig().nativeInstrumentId?.split(".")[0]
|
|
8
|
-
: "";
|
|
9
|
-
|
|
10
5
|
/**
|
|
11
6
|
* Returns list of operations associated to an account.
|
|
12
7
|
* @param partyId Account partyId
|
|
@@ -18,37 +13,31 @@ export async function listOperations(
|
|
|
18
13
|
partyId: string,
|
|
19
14
|
page: Pagination,
|
|
20
15
|
): Promise<[Operation[], string]> {
|
|
21
|
-
const {
|
|
16
|
+
const { operations, next } = await getOperations(partyId, {
|
|
22
17
|
cursor: page.pagingToken !== undefined ? parseInt(page.pagingToken) : undefined,
|
|
23
18
|
minOffset: page.minHeight,
|
|
24
19
|
limit: page.limit,
|
|
25
20
|
});
|
|
26
21
|
const ops: Operation[] = [];
|
|
27
|
-
for (const tx of
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
fees: BigInt(0), // to be finalized when details are available on backend
|
|
44
|
-
date: new Date(tx.record_time.seconds),
|
|
45
|
-
block: {
|
|
46
|
-
height: tx.offset,
|
|
47
|
-
time: new Date(tx.effective_at.seconds),
|
|
48
|
-
},
|
|
22
|
+
for (const tx of operations) {
|
|
23
|
+
if (tx.type === "Send") {
|
|
24
|
+
ops.push({
|
|
25
|
+
id: tx.uid,
|
|
26
|
+
type: tx.senders.includes(partyId) ? "OUT" : "IN",
|
|
27
|
+
value: BigInt(tx.transfers[0].value),
|
|
28
|
+
senders: tx.senders,
|
|
29
|
+
recipients: tx.recipients,
|
|
30
|
+
asset: tx.asset,
|
|
31
|
+
tx: {
|
|
32
|
+
hash: tx.block.hash,
|
|
33
|
+
fees: BigInt(tx.fee.value),
|
|
34
|
+
date: new Date(tx.transaction_timestamp),
|
|
35
|
+
block: {
|
|
36
|
+
height: tx.block.height,
|
|
37
|
+
time: new Date(tx.block.time),
|
|
49
38
|
},
|
|
50
|
-
}
|
|
51
|
-
}
|
|
39
|
+
},
|
|
40
|
+
});
|
|
52
41
|
}
|
|
53
42
|
}
|
|
54
43
|
return [ops, next + ""];
|
|
@@ -8,7 +8,7 @@ jest.mock("../../network/gateway", () => ({
|
|
|
8
8
|
|
|
9
9
|
const mockSerialized = JSON.stringify({
|
|
10
10
|
serialized: "serialized-tx",
|
|
11
|
-
signature: "
|
|
11
|
+
signature: "signature__PARTY__alice:123",
|
|
12
12
|
});
|
|
13
13
|
|
|
14
14
|
describe("broadcast", () => {
|
|
@@ -23,11 +23,11 @@ describe("broadcast", () => {
|
|
|
23
23
|
useGateway: true,
|
|
24
24
|
} as any);
|
|
25
25
|
|
|
26
|
-
(submit as jest.Mock).mockResolvedValue({
|
|
26
|
+
(submit as jest.Mock).mockResolvedValue({ update_id: "my-update-id" });
|
|
27
27
|
|
|
28
28
|
const result = await broadcast(mockSerialized);
|
|
29
29
|
|
|
30
|
-
expect(submit).toHaveBeenCalledWith("serialized-tx", "signature");
|
|
30
|
+
expect(submit).toHaveBeenCalledWith("alice:123", "serialized-tx", "signature");
|
|
31
31
|
expect(result).toEqual("my-update-id");
|
|
32
32
|
});
|
|
33
33
|
|
|
@@ -5,6 +5,7 @@ const useGateway = () => coinConfig.getCoinConfig().useGateway === true;
|
|
|
5
5
|
|
|
6
6
|
export async function broadcast(signedTx: string): Promise<string> {
|
|
7
7
|
const parsed: { serialized: string; signature: string } = JSON.parse(signedTx);
|
|
8
|
-
|
|
8
|
+
const [sig, party] = parsed.signature.split("__PARTY__");
|
|
9
|
+
if (useGateway()) return (await submit(party, parsed.serialized, sig)).update_id;
|
|
9
10
|
else throw new Error("Not implemented");
|
|
10
11
|
}
|
|
@@ -3,25 +3,15 @@ import { combine } from "./combine";
|
|
|
3
3
|
describe("combine", () => {
|
|
4
4
|
it("responds with a Stringify version of the payload to broadcast", () => {
|
|
5
5
|
// GIVEN
|
|
6
|
-
const transaction =
|
|
7
|
-
transaction: {
|
|
8
|
-
serialized: "SERIALIZED",
|
|
9
|
-
json: "JSON",
|
|
10
|
-
hash: "HASH",
|
|
11
|
-
},
|
|
12
|
-
};
|
|
6
|
+
const transaction = "0x000000001";
|
|
13
7
|
const signature = "SIGNATURE";
|
|
14
8
|
|
|
15
9
|
// WHEN
|
|
16
|
-
const result = combine(
|
|
10
|
+
const result = combine(transaction, signature);
|
|
17
11
|
|
|
18
12
|
// THEN
|
|
19
13
|
expect(JSON.parse(result)).toEqual({
|
|
20
|
-
|
|
21
|
-
serialized: "SERIALIZED",
|
|
22
|
-
json: "JSON",
|
|
23
|
-
hash: "HASH",
|
|
24
|
-
},
|
|
14
|
+
serialized: "0x000000001",
|
|
25
15
|
signature: "SIGNATURE",
|
|
26
16
|
});
|
|
27
17
|
});
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
// Combines signature with raw transaction
|
|
2
|
-
export function combine(
|
|
3
|
-
const tx = JSON.parse(transaction);
|
|
4
|
-
|
|
2
|
+
export function combine(serialized: string, signature: string): string {
|
|
5
3
|
return JSON.stringify({
|
|
6
|
-
|
|
4
|
+
serialized,
|
|
7
5
|
signature,
|
|
8
6
|
});
|
|
9
7
|
}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import BigNumber from "bignumber.js";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
const encodeNativeTx = (nativeTx: BoilerplateNativeTransaction) => JSON.stringify(nativeTx);
|
|
2
|
+
import { prepareTransferRequest, PrepareTransferResponse } from "../../network/gateway";
|
|
5
3
|
|
|
6
4
|
export async function craftTransaction(
|
|
7
5
|
account: {
|
|
@@ -12,25 +10,25 @@ export async function craftTransaction(
|
|
|
12
10
|
transaction: {
|
|
13
11
|
recipient?: string;
|
|
14
12
|
amount: BigNumber;
|
|
15
|
-
|
|
13
|
+
tokenId: string;
|
|
14
|
+
expireInSeconds: number;
|
|
16
15
|
},
|
|
17
16
|
): Promise<{
|
|
18
|
-
nativeTransaction:
|
|
17
|
+
nativeTransaction: PrepareTransferResponse;
|
|
19
18
|
serializedTransaction: string;
|
|
19
|
+
hash: string;
|
|
20
20
|
}> {
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
const serializedTransaction = encodeNativeTx(nativeTransaction);
|
|
21
|
+
const { serialized, json, hash } = await prepareTransferRequest(account.address, {
|
|
22
|
+
recipient: transaction.recipient || "",
|
|
23
|
+
amount: transaction.amount.toNumber(),
|
|
24
|
+
type: "token-transfer-request",
|
|
25
|
+
execute_before_secs: transaction.expireInSeconds,
|
|
26
|
+
instrument_id: transaction.tokenId,
|
|
27
|
+
});
|
|
31
28
|
|
|
32
29
|
return {
|
|
33
|
-
nativeTransaction,
|
|
34
|
-
serializedTransaction,
|
|
30
|
+
nativeTransaction: json,
|
|
31
|
+
serializedTransaction: serialized,
|
|
32
|
+
hash,
|
|
35
33
|
};
|
|
36
34
|
}
|