@ledgerhq/coin-canton 0.5.0-nightly.4 → 0.5.0-nightly.6
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/CHANGELOG.md +20 -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 +20 -28
- package/lib/api/index.js.map +1 -1
- package/lib/api/lastBlock.integ.test.js +1 -1
- package/lib/api/lastBlock.integ.test.js.map +1 -1
- package/lib/api/listOperations.integ.test.js +1 -1
- package/lib/api/listOperations.integ.test.js.map +1 -1
- package/lib/bridge/broadcast.d.ts.map +1 -1
- package/lib/bridge/broadcast.js +2 -2
- package/lib/bridge/broadcast.js.map +1 -1
- package/lib/bridge/broadcast.test.js +9 -0
- package/lib/bridge/broadcast.test.js.map +1 -1
- package/lib/bridge/createTransaction.js +1 -1
- package/lib/bridge/createTransaction.js.map +1 -1
- package/lib/bridge/getTransactionStatus.js +1 -1
- package/lib/bridge/getTransactionStatus.js.map +1 -1
- package/lib/bridge/onboard.d.ts +4 -3
- package/lib/bridge/onboard.d.ts.map +1 -1
- package/lib/bridge/onboard.integ.test.js +11 -8
- package/lib/bridge/onboard.integ.test.js.map +1 -1
- package/lib/bridge/onboard.js +24 -16
- package/lib/bridge/onboard.js.map +1 -1
- package/lib/bridge/prepareTransaction.js +1 -1
- package/lib/bridge/prepareTransaction.js.map +1 -1
- package/lib/bridge/signOperation.d.ts.map +1 -1
- package/lib/bridge/signOperation.js +10 -5
- package/lib/bridge/signOperation.js.map +1 -1
- package/lib/bridge/sync.d.ts.map +1 -1
- package/lib/bridge/sync.js +28 -20
- package/lib/bridge/sync.js.map +1 -1
- package/lib/common-logic/account/getBalance.d.ts +2 -1
- package/lib/common-logic/account/getBalance.d.ts.map +1 -1
- package/lib/common-logic/account/getBalance.js +7 -7
- package/lib/common-logic/account/getBalance.js.map +1 -1
- package/lib/common-logic/account/getBalance.unit.test.js +6 -3
- package/lib/common-logic/account/getBalance.unit.test.js.map +1 -1
- package/lib/common-logic/history/lastBlock.d.ts +2 -1
- package/lib/common-logic/history/lastBlock.d.ts.map +1 -1
- package/lib/common-logic/history/lastBlock.js +3 -3
- package/lib/common-logic/history/lastBlock.js.map +1 -1
- package/lib/common-logic/history/lastBlock.test.js +5 -2
- package/lib/common-logic/history/lastBlock.test.js.map +1 -1
- package/lib/common-logic/history/listOperations.d.ts +2 -1
- package/lib/common-logic/history/listOperations.d.ts.map +1 -1
- package/lib/common-logic/history/listOperations.js +2 -2
- package/lib/common-logic/history/listOperations.js.map +1 -1
- package/lib/common-logic/transaction/broadcast.d.ts +2 -1
- package/lib/common-logic/transaction/broadcast.d.ts.map +1 -1
- package/lib/common-logic/transaction/broadcast.js +4 -4
- package/lib/common-logic/transaction/broadcast.js.map +1 -1
- package/lib/common-logic/transaction/broadcast.test.js +6 -3
- package/lib/common-logic/transaction/broadcast.test.js.map +1 -1
- package/lib/common-logic/transaction/craftTransaction.d.ts +3 -1
- package/lib/common-logic/transaction/craftTransaction.d.ts.map +1 -1
- package/lib/common-logic/transaction/craftTransaction.js +8 -4
- package/lib/common-logic/transaction/craftTransaction.js.map +1 -1
- package/lib/common-logic/transaction/estimateFees.d.ts +2 -1
- package/lib/common-logic/transaction/estimateFees.d.ts.map +1 -1
- package/lib/common-logic/transaction/estimateFees.js +3 -4
- package/lib/common-logic/transaction/estimateFees.js.map +1 -1
- package/lib/network/gateway.d.ts +24 -14
- package/lib/network/gateway.d.ts.map +1 -1
- package/lib/network/gateway.integ.test.js +17 -14
- package/lib/network/gateway.integ.test.js.map +1 -1
- package/lib/network/gateway.js +33 -33
- package/lib/network/gateway.js.map +1 -1
- package/lib/types/bridge.d.ts +5 -2
- package/lib/types/bridge.d.ts.map +1 -1
- 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 +19 -27
- package/lib-es/api/index.js.map +1 -1
- package/lib-es/api/lastBlock.integ.test.js +1 -1
- package/lib-es/api/lastBlock.integ.test.js.map +1 -1
- package/lib-es/api/listOperations.integ.test.js +1 -1
- package/lib-es/api/listOperations.integ.test.js.map +1 -1
- package/lib-es/bridge/broadcast.d.ts.map +1 -1
- package/lib-es/bridge/broadcast.js +2 -2
- package/lib-es/bridge/broadcast.js.map +1 -1
- package/lib-es/bridge/broadcast.test.js +9 -0
- package/lib-es/bridge/broadcast.test.js.map +1 -1
- package/lib-es/bridge/createTransaction.js +1 -1
- package/lib-es/bridge/createTransaction.js.map +1 -1
- package/lib-es/bridge/getTransactionStatus.js +1 -1
- package/lib-es/bridge/getTransactionStatus.js.map +1 -1
- package/lib-es/bridge/onboard.d.ts +4 -3
- package/lib-es/bridge/onboard.d.ts.map +1 -1
- package/lib-es/bridge/onboard.integ.test.js +11 -8
- package/lib-es/bridge/onboard.integ.test.js.map +1 -1
- package/lib-es/bridge/onboard.js +24 -16
- package/lib-es/bridge/onboard.js.map +1 -1
- package/lib-es/bridge/prepareTransaction.js +1 -1
- 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 +10 -5
- package/lib-es/bridge/signOperation.js.map +1 -1
- package/lib-es/bridge/sync.d.ts.map +1 -1
- package/lib-es/bridge/sync.js +28 -20
- package/lib-es/bridge/sync.js.map +1 -1
- package/lib-es/common-logic/account/getBalance.d.ts +2 -1
- package/lib-es/common-logic/account/getBalance.d.ts.map +1 -1
- package/lib-es/common-logic/account/getBalance.js +7 -7
- package/lib-es/common-logic/account/getBalance.js.map +1 -1
- package/lib-es/common-logic/account/getBalance.unit.test.js +6 -3
- package/lib-es/common-logic/account/getBalance.unit.test.js.map +1 -1
- package/lib-es/common-logic/history/lastBlock.d.ts +2 -1
- package/lib-es/common-logic/history/lastBlock.d.ts.map +1 -1
- package/lib-es/common-logic/history/lastBlock.js +3 -3
- package/lib-es/common-logic/history/lastBlock.js.map +1 -1
- package/lib-es/common-logic/history/lastBlock.test.js +5 -2
- package/lib-es/common-logic/history/lastBlock.test.js.map +1 -1
- package/lib-es/common-logic/history/listOperations.d.ts +2 -1
- package/lib-es/common-logic/history/listOperations.d.ts.map +1 -1
- package/lib-es/common-logic/history/listOperations.js +2 -2
- package/lib-es/common-logic/history/listOperations.js.map +1 -1
- package/lib-es/common-logic/transaction/broadcast.d.ts +2 -1
- package/lib-es/common-logic/transaction/broadcast.d.ts.map +1 -1
- package/lib-es/common-logic/transaction/broadcast.js +4 -4
- package/lib-es/common-logic/transaction/broadcast.js.map +1 -1
- package/lib-es/common-logic/transaction/broadcast.test.js +6 -3
- package/lib-es/common-logic/transaction/broadcast.test.js.map +1 -1
- package/lib-es/common-logic/transaction/craftTransaction.d.ts +3 -1
- package/lib-es/common-logic/transaction/craftTransaction.d.ts.map +1 -1
- package/lib-es/common-logic/transaction/craftTransaction.js +9 -5
- package/lib-es/common-logic/transaction/craftTransaction.js.map +1 -1
- package/lib-es/common-logic/transaction/estimateFees.d.ts +2 -1
- package/lib-es/common-logic/transaction/estimateFees.d.ts.map +1 -1
- package/lib-es/common-logic/transaction/estimateFees.js +3 -4
- package/lib-es/common-logic/transaction/estimateFees.js.map +1 -1
- package/lib-es/network/gateway.d.ts +24 -14
- package/lib-es/network/gateway.d.ts.map +1 -1
- package/lib-es/network/gateway.integ.test.js +17 -14
- package/lib-es/network/gateway.integ.test.js.map +1 -1
- package/lib-es/network/gateway.js +33 -33
- package/lib-es/network/gateway.js.map +1 -1
- package/lib-es/types/bridge.d.ts +5 -2
- package/lib-es/types/bridge.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/api/getBalance.integ.test.ts +1 -1
- package/src/api/index.ts +22 -51
- package/src/api/lastBlock.integ.test.ts +1 -1
- package/src/api/listOperations.integ.test.ts +1 -1
- package/src/bridge/broadcast.test.ts +11 -0
- package/src/bridge/broadcast.ts +5 -2
- package/src/bridge/createTransaction.ts +1 -1
- package/src/bridge/getTransactionStatus.ts +1 -1
- package/src/bridge/onboard.integ.test.ts +22 -10
- package/src/bridge/onboard.ts +32 -13
- package/src/bridge/prepareTransaction.ts +1 -1
- package/src/bridge/signOperation.ts +20 -7
- package/src/bridge/sync.ts +28 -23
- package/src/common-logic/account/getBalance.ts +12 -7
- package/src/common-logic/account/getBalance.unit.test.ts +8 -3
- package/src/common-logic/history/lastBlock.test.ts +7 -2
- package/src/common-logic/history/lastBlock.ts +5 -3
- package/src/common-logic/history/listOperations.ts +3 -2
- package/src/common-logic/transaction/broadcast.test.ts +8 -3
- package/src/common-logic/transaction/broadcast.ts +6 -3
- package/src/common-logic/transaction/craftTransaction.ts +22 -5
- package/src/common-logic/transaction/estimateFees.ts +5 -4
- package/src/network/gateway.integ.test.ts +29 -11
- package/src/network/gateway.ts +66 -35
- package/src/types/bridge.ts +5 -0
|
@@ -10,10 +10,14 @@ import {
|
|
|
10
10
|
CantonPreApprovalResult,
|
|
11
11
|
} from "../types/onboard";
|
|
12
12
|
import coinConfig from "../config";
|
|
13
|
+
import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
13
14
|
|
|
14
15
|
describe("onboard (devnet)", () => {
|
|
15
16
|
const mockDeviceId = "test-device-id";
|
|
16
17
|
const mockDerivationPath = "44'/6767'/0'/0'/0'";
|
|
18
|
+
const mockCurrency = {
|
|
19
|
+
id: "canton_network",
|
|
20
|
+
} as unknown as CryptoCurrency;
|
|
17
21
|
|
|
18
22
|
let onboardedAccount: {
|
|
19
23
|
keyPair: ReturnType<typeof generateMockKeyPair>;
|
|
@@ -53,7 +57,7 @@ describe("onboard (devnet)", () => {
|
|
|
53
57
|
|
|
54
58
|
const onboardObservable = buildOnboardAccount(mockSignerContext);
|
|
55
59
|
const onboardValues = await firstValueFrom(
|
|
56
|
-
onboardObservable(mockDeviceId, mockDerivationPath).pipe(toArray()),
|
|
60
|
+
onboardObservable(mockCurrency, mockDeviceId, mockDerivationPath).pipe(toArray()),
|
|
57
61
|
);
|
|
58
62
|
const onboardResult = onboardValues.find(
|
|
59
63
|
(value): value is CantonOnboardResult => "partyId" in value,
|
|
@@ -72,7 +76,7 @@ describe("onboard (devnet)", () => {
|
|
|
72
76
|
};
|
|
73
77
|
|
|
74
78
|
// WHEN
|
|
75
|
-
const result = await isAccountOnboarded(keyPair.publicKeyHex);
|
|
79
|
+
const result = await isAccountOnboarded(mockCurrency, keyPair.publicKeyHex);
|
|
76
80
|
|
|
77
81
|
// THEN
|
|
78
82
|
expect(result).not.toBe(false);
|
|
@@ -87,7 +91,7 @@ describe("onboard (devnet)", () => {
|
|
|
87
91
|
const keyPair = generateMockKeyPair();
|
|
88
92
|
|
|
89
93
|
// WHEN
|
|
90
|
-
const result = await isAccountOnboarded(keyPair.publicKeyHex);
|
|
94
|
+
const result = await isAccountOnboarded(mockCurrency, keyPair.publicKeyHex);
|
|
91
95
|
|
|
92
96
|
// THEN
|
|
93
97
|
expect(result).toEqual({ isOnboarded: false });
|
|
@@ -98,7 +102,7 @@ describe("onboard (devnet)", () => {
|
|
|
98
102
|
const keyPair = generateMockKeyPair();
|
|
99
103
|
|
|
100
104
|
// WHEN
|
|
101
|
-
const result = await isAccountOnboarded(keyPair.publicKeyHex);
|
|
105
|
+
const result = await isAccountOnboarded(mockCurrency, keyPair.publicKeyHex);
|
|
102
106
|
|
|
103
107
|
// THEN
|
|
104
108
|
expect(result).toEqual({ isOnboarded: false });
|
|
@@ -117,7 +121,7 @@ describe("onboard (devnet)", () => {
|
|
|
117
121
|
|
|
118
122
|
// WHEN
|
|
119
123
|
const allValues = await firstValueFrom(
|
|
120
|
-
onboardObservable(mockDeviceId, mockDerivationPath).pipe(toArray()),
|
|
124
|
+
onboardObservable(mockCurrency, mockDeviceId, mockDerivationPath).pipe(toArray()),
|
|
121
125
|
);
|
|
122
126
|
const progressValues = allValues.filter(
|
|
123
127
|
(value): value is CantonOnboardProgress => "status" in value && !("partyId" in value),
|
|
@@ -149,7 +153,7 @@ describe("onboard (devnet)", () => {
|
|
|
149
153
|
|
|
150
154
|
// WHEN
|
|
151
155
|
const secondOnboardValues = await firstValueFrom(
|
|
152
|
-
secondOnboardObservable(mockDeviceId, mockDerivationPath).pipe(toArray()),
|
|
156
|
+
secondOnboardObservable(mockCurrency, mockDeviceId, mockDerivationPath).pipe(toArray()),
|
|
153
157
|
);
|
|
154
158
|
const secondResult = secondOnboardValues.find(
|
|
155
159
|
(value): value is CantonOnboardResult => "partyId" in value,
|
|
@@ -170,9 +174,12 @@ describe("onboard (devnet)", () => {
|
|
|
170
174
|
|
|
171
175
|
// WHEN
|
|
172
176
|
const preapprovalValues = await firstValueFrom(
|
|
173
|
-
preapprovalObservable(
|
|
174
|
-
|
|
175
|
-
|
|
177
|
+
preapprovalObservable(
|
|
178
|
+
mockCurrency,
|
|
179
|
+
mockDeviceId,
|
|
180
|
+
mockDerivationPath,
|
|
181
|
+
onboardResult.partyId,
|
|
182
|
+
).pipe(toArray()),
|
|
176
183
|
);
|
|
177
184
|
|
|
178
185
|
const progressValues = preapprovalValues.filter(
|
|
@@ -208,7 +215,12 @@ describe("onboard (devnet)", () => {
|
|
|
208
215
|
// WHEN & THEN
|
|
209
216
|
try {
|
|
210
217
|
await firstValueFrom(
|
|
211
|
-
preapprovalObservable(
|
|
218
|
+
preapprovalObservable(
|
|
219
|
+
mockCurrency,
|
|
220
|
+
mockDeviceId,
|
|
221
|
+
mockDerivationPath,
|
|
222
|
+
"invalid-party-id-123",
|
|
223
|
+
),
|
|
212
224
|
);
|
|
213
225
|
expect(true).toBe(true);
|
|
214
226
|
} catch (error) {
|
package/src/bridge/onboard.ts
CHANGED
|
@@ -2,10 +2,9 @@ import { Observable } from "rxjs";
|
|
|
2
2
|
import { SignerContext } from "@ledgerhq/coin-framework/signer";
|
|
3
3
|
import { emptyHistoryCache } from "@ledgerhq/coin-framework/account/index";
|
|
4
4
|
import { getDerivationModesForCurrency } from "@ledgerhq/coin-framework/derivation";
|
|
5
|
-
import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/currencies";
|
|
6
5
|
import { getAccountShape } from "./sync";
|
|
7
6
|
import { CantonAccount, CantonSigner } from "../types";
|
|
8
|
-
import type { Account } from "@ledgerhq/types-live";
|
|
7
|
+
import type { Account, DerivationMode } from "@ledgerhq/types-live";
|
|
9
8
|
import {
|
|
10
9
|
prepareOnboarding,
|
|
11
10
|
submitOnboarding,
|
|
@@ -25,6 +24,7 @@ import {
|
|
|
25
24
|
PrepareTransactionResponse,
|
|
26
25
|
} from "../types/onboard";
|
|
27
26
|
import resolver from "../signer";
|
|
27
|
+
import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
28
28
|
|
|
29
29
|
async function _getKeypair(
|
|
30
30
|
signerContext: SignerContext<CantonSigner>,
|
|
@@ -37,14 +37,12 @@ async function _getKeypair(
|
|
|
37
37
|
});
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
const currency = getCryptoCurrencyById("canton_network");
|
|
41
|
-
const derivationMode = getDerivationModesForCurrency(currency)[0];
|
|
42
|
-
|
|
43
40
|
export const isAccountOnboarded = async (
|
|
41
|
+
currency: CryptoCurrency,
|
|
44
42
|
publicKey: string,
|
|
45
43
|
): Promise<{ isOnboarded: boolean; party_id?: string }> => {
|
|
46
44
|
try {
|
|
47
|
-
const { party_id } = await getPartyByPubKey(publicKey);
|
|
45
|
+
const { party_id } = await getPartyByPubKey(currency, publicKey);
|
|
48
46
|
|
|
49
47
|
if (party_id) {
|
|
50
48
|
return { isOnboarded: true, party_id };
|
|
@@ -60,6 +58,7 @@ export const isAccountOnboarded = async (
|
|
|
60
58
|
export const buildOnboardAccount =
|
|
61
59
|
(signerContext: SignerContext<CantonSigner>) =>
|
|
62
60
|
(
|
|
61
|
+
currency: CryptoCurrency,
|
|
63
62
|
deviceId: string,
|
|
64
63
|
derivationPath: string,
|
|
65
64
|
): Observable<CantonOnboardProgress | CantonOnboardResult> =>
|
|
@@ -68,6 +67,7 @@ export const buildOnboardAccount =
|
|
|
68
67
|
observer.next({
|
|
69
68
|
status: OnboardStatus.INIT,
|
|
70
69
|
});
|
|
70
|
+
const derivationMode = getDerivationModesForCurrency(currency)[0];
|
|
71
71
|
const getAddress = resolver(signerContext);
|
|
72
72
|
const { address, publicKey } = await getAddress(deviceId, {
|
|
73
73
|
path: derivationPath,
|
|
@@ -79,9 +79,15 @@ export const buildOnboardAccount =
|
|
|
79
79
|
status: OnboardStatus.PREPARE,
|
|
80
80
|
});
|
|
81
81
|
|
|
82
|
-
const { party_id: partyId } = await isAccountOnboarded(publicKey);
|
|
82
|
+
const { party_id: partyId } = await isAccountOnboarded(currency, publicKey);
|
|
83
83
|
if (partyId) {
|
|
84
|
-
const account = await createAccount({
|
|
84
|
+
const account = await createAccount({
|
|
85
|
+
address,
|
|
86
|
+
derivationPath,
|
|
87
|
+
partyId,
|
|
88
|
+
currency,
|
|
89
|
+
derivationMode,
|
|
90
|
+
});
|
|
85
91
|
observer.next({
|
|
86
92
|
partyId,
|
|
87
93
|
account,
|
|
@@ -90,7 +96,7 @@ export const buildOnboardAccount =
|
|
|
90
96
|
return;
|
|
91
97
|
}
|
|
92
98
|
|
|
93
|
-
const preparedTransaction = await prepareOnboarding(publicKey, "ed25519");
|
|
99
|
+
const preparedTransaction = await prepareOnboarding(currency, publicKey, "ed25519");
|
|
94
100
|
|
|
95
101
|
observer.next({
|
|
96
102
|
status: OnboardStatus.SIGN,
|
|
@@ -105,6 +111,7 @@ export const buildOnboardAccount =
|
|
|
105
111
|
});
|
|
106
112
|
|
|
107
113
|
const result = await submitOnboarding(
|
|
114
|
+
currency,
|
|
108
115
|
{ public_key: publicKey, public_key_type: "ed25519" },
|
|
109
116
|
preparedTransaction,
|
|
110
117
|
signature,
|
|
@@ -114,6 +121,8 @@ export const buildOnboardAccount =
|
|
|
114
121
|
address,
|
|
115
122
|
derivationPath,
|
|
116
123
|
partyId: preparedTransaction.party_id,
|
|
124
|
+
currency,
|
|
125
|
+
derivationMode,
|
|
117
126
|
});
|
|
118
127
|
observer.next({
|
|
119
128
|
partyId: preparedTransaction.party_id,
|
|
@@ -132,6 +141,8 @@ export const buildOnboardAccount =
|
|
|
132
141
|
address,
|
|
133
142
|
derivationPath,
|
|
134
143
|
partyId: result.party.party_id,
|
|
144
|
+
currency,
|
|
145
|
+
derivationMode,
|
|
135
146
|
});
|
|
136
147
|
observer.next({
|
|
137
148
|
partyId: result.party.party_id,
|
|
@@ -154,6 +165,7 @@ export const buildOnboardAccount =
|
|
|
154
165
|
export const buildAuthorizePreapproval =
|
|
155
166
|
(signerContext: SignerContext<CantonSigner>) =>
|
|
156
167
|
(
|
|
168
|
+
currency: CryptoCurrency,
|
|
157
169
|
deviceId: string,
|
|
158
170
|
derivationPath: string,
|
|
159
171
|
partyId: string,
|
|
@@ -164,8 +176,10 @@ export const buildAuthorizePreapproval =
|
|
|
164
176
|
status: PreApprovalStatus.PREPARE,
|
|
165
177
|
});
|
|
166
178
|
|
|
167
|
-
const preparedTransaction: PrepareTransactionResponse =
|
|
168
|
-
|
|
179
|
+
const preparedTransaction: PrepareTransactionResponse = await preparePreApprovalTransaction(
|
|
180
|
+
currency,
|
|
181
|
+
partyId,
|
|
182
|
+
);
|
|
169
183
|
|
|
170
184
|
observer.next({
|
|
171
185
|
status: PreApprovalStatus.SIGN,
|
|
@@ -180,6 +194,7 @@ export const buildAuthorizePreapproval =
|
|
|
180
194
|
});
|
|
181
195
|
|
|
182
196
|
const { isApproved } = await submitPreApprovalTransaction(
|
|
197
|
+
currency,
|
|
183
198
|
partyId,
|
|
184
199
|
preparedTransaction,
|
|
185
200
|
signature,
|
|
@@ -195,7 +210,7 @@ export const buildAuthorizePreapproval =
|
|
|
195
210
|
|
|
196
211
|
const handleTapRequest = async () => {
|
|
197
212
|
try {
|
|
198
|
-
const { serialized, hash } = await prepareTapRequest({
|
|
213
|
+
const { serialized, hash } = await prepareTapRequest(currency, {
|
|
199
214
|
partyId,
|
|
200
215
|
});
|
|
201
216
|
|
|
@@ -212,7 +227,7 @@ export const buildAuthorizePreapproval =
|
|
|
212
227
|
status: PreApprovalStatus.SUBMIT,
|
|
213
228
|
});
|
|
214
229
|
|
|
215
|
-
await submitTapRequest({
|
|
230
|
+
await submitTapRequest(currency, {
|
|
216
231
|
partyId,
|
|
217
232
|
serialized,
|
|
218
233
|
signature,
|
|
@@ -244,11 +259,15 @@ const createAccount = async ({
|
|
|
244
259
|
address,
|
|
245
260
|
partyId,
|
|
246
261
|
derivationPath,
|
|
262
|
+
currency,
|
|
263
|
+
derivationMode,
|
|
247
264
|
index = 0,
|
|
248
265
|
}: {
|
|
249
266
|
address: string;
|
|
250
267
|
derivationPath: string;
|
|
251
268
|
partyId: string;
|
|
269
|
+
currency: CryptoCurrency;
|
|
270
|
+
derivationMode: DerivationMode;
|
|
252
271
|
index?: number;
|
|
253
272
|
}): Promise<Partial<Account>> => {
|
|
254
273
|
const accountShape = await getAccountShape(
|
|
@@ -10,7 +10,7 @@ export const prepareTransaction: AccountBridge<Transaction>["prepareTransaction"
|
|
|
10
10
|
) => {
|
|
11
11
|
let fee = transaction.fee;
|
|
12
12
|
if (!fee || fee.eq(0)) {
|
|
13
|
-
fee = BigNumber((await estimateFees(
|
|
13
|
+
fee = BigNumber((await estimateFees(account.currency)).toString());
|
|
14
14
|
}
|
|
15
15
|
return updateTransaction(transaction, { fee });
|
|
16
16
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Observable } from "rxjs";
|
|
2
|
+
import BigNumber from "bignumber.js";
|
|
2
3
|
import { FeeNotLoaded } from "@ledgerhq/errors";
|
|
3
4
|
import { AccountBridge, Operation } from "@ledgerhq/types-live";
|
|
4
5
|
import { SignerContext } from "@ledgerhq/coin-framework/signer";
|
|
@@ -22,18 +23,30 @@ export const buildSignOperation =
|
|
|
22
23
|
|
|
23
24
|
const signature = await signerContext(deviceId, async signer => {
|
|
24
25
|
const { freshAddressPath: derivationPath } = account;
|
|
25
|
-
const partyId = account
|
|
26
|
+
const partyId = (account as unknown as { cantonResources: { partyId: string } })
|
|
27
|
+
.cantonResources.partyId;
|
|
28
|
+
const params: {
|
|
29
|
+
recipient?: string;
|
|
30
|
+
amount: BigNumber;
|
|
31
|
+
tokenId: string;
|
|
32
|
+
expireInSeconds: number;
|
|
33
|
+
memo?: string;
|
|
34
|
+
} = {
|
|
35
|
+
recipient: transaction.recipient,
|
|
36
|
+
amount: transaction.amount,
|
|
37
|
+
expireInSeconds: 60 * 60,
|
|
38
|
+
tokenId: "Amulet",
|
|
39
|
+
};
|
|
40
|
+
if (transaction.memo) {
|
|
41
|
+
params.memo = transaction.memo;
|
|
42
|
+
}
|
|
26
43
|
|
|
27
44
|
const { hash, serializedTransaction } = await craftTransaction(
|
|
45
|
+
account.currency,
|
|
28
46
|
{
|
|
29
47
|
address: partyId,
|
|
30
48
|
},
|
|
31
|
-
|
|
32
|
-
recipient: transaction.recipient,
|
|
33
|
-
amount: transaction.amount,
|
|
34
|
-
expireInSeconds: 60 * 60,
|
|
35
|
-
tokenId: "Amulet",
|
|
36
|
-
},
|
|
49
|
+
params,
|
|
37
50
|
);
|
|
38
51
|
const transactionSignature = await signer.signTransaction(derivationPath, hash);
|
|
39
52
|
|
package/src/bridge/sync.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import BigNumber from "bignumber.js";
|
|
2
|
-
import { Operation } from "@ledgerhq/types-live";
|
|
2
|
+
import { Operation, OperationType } from "@ledgerhq/types-live";
|
|
3
3
|
import { decodeAccountId, encodeAccountId } from "@ledgerhq/coin-framework/account/index";
|
|
4
4
|
import { GetAccountShape, mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers";
|
|
5
5
|
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
|
|
@@ -18,11 +18,17 @@ const txInfoToOperationAdapter =
|
|
|
18
18
|
recipients,
|
|
19
19
|
transaction_timestamp,
|
|
20
20
|
fee: { value: fee },
|
|
21
|
-
transfers: [{ value: transferValue }],
|
|
21
|
+
transfers: [{ value: transferValue, details }],
|
|
22
22
|
} = txInfo;
|
|
23
|
-
|
|
23
|
+
let type: OperationType = "UNKNOWN";
|
|
24
|
+
if (txInfo.type === "Send") {
|
|
25
|
+
type = senders.includes(partyId) ? "OUT" : "IN";
|
|
26
|
+
} else if (txInfo.type === "Receive") {
|
|
27
|
+
type = "IN";
|
|
28
|
+
}
|
|
24
29
|
const value = new BigNumber(transferValue);
|
|
25
30
|
const feeValue = new BigNumber(fee);
|
|
31
|
+
const memo = details.metadata.reason;
|
|
26
32
|
|
|
27
33
|
const op: Operation = {
|
|
28
34
|
id: encodeOperationId(accountId, transaction_hash, type),
|
|
@@ -39,6 +45,7 @@ const txInfoToOperationAdapter =
|
|
|
39
45
|
transactionSequenceNumber: height,
|
|
40
46
|
extra: {
|
|
41
47
|
uid,
|
|
48
|
+
memo,
|
|
42
49
|
},
|
|
43
50
|
};
|
|
44
51
|
|
|
@@ -50,9 +57,7 @@ const filterOperations = (
|
|
|
50
57
|
accountId: string,
|
|
51
58
|
partyId: string,
|
|
52
59
|
): Operation[] => {
|
|
53
|
-
return transactions
|
|
54
|
-
.filter(tx => tx.type === "Receive" || tx.type === "Send")
|
|
55
|
-
.map(txInfoToOperationAdapter(accountId, partyId));
|
|
60
|
+
return transactions.map(txInfoToOperationAdapter(accountId, partyId));
|
|
56
61
|
};
|
|
57
62
|
|
|
58
63
|
export const getAccountShape: GetAccountShape<CantonAccount> = async info => {
|
|
@@ -75,39 +80,39 @@ export const getAccountShape: GetAccountShape<CantonAccount> = async info => {
|
|
|
75
80
|
derivationMode,
|
|
76
81
|
});
|
|
77
82
|
|
|
78
|
-
// blockheight retrieval
|
|
79
|
-
const blockHeight = await getLedgerEnd();
|
|
80
|
-
|
|
81
83
|
// Account info retrieval + spendable balance calculation
|
|
82
84
|
// const accountInfo = await getAccountInfo(address);
|
|
83
|
-
const balances = await getBalance(partyId);
|
|
85
|
+
const balances = await getBalance(currency, partyId);
|
|
84
86
|
|
|
85
|
-
|
|
86
|
-
const balanceData = balances.find(balance => balance.instrument_id.includes("Amulet")) || {
|
|
87
|
+
const balanceData = balances.find(balance => balance.instrument_id === "Amulet") || {
|
|
87
88
|
instrument_id: "Amulet",
|
|
88
89
|
amount: 0,
|
|
89
90
|
locked: false,
|
|
90
91
|
};
|
|
91
92
|
|
|
92
93
|
const balance = new BigNumber(balanceData.amount);
|
|
93
|
-
const reserveMin = coinConfig.getCoinConfig().minReserve || 0;
|
|
94
|
+
const reserveMin = coinConfig.getCoinConfig(currency).minReserve || 0;
|
|
94
95
|
const lockedAmount = balanceData.locked ? balance : new BigNumber(0);
|
|
95
96
|
const spendableBalance = BigNumber.max(
|
|
96
97
|
0,
|
|
97
98
|
balance.minus(lockedAmount).minus(BigNumber(reserveMin)),
|
|
98
99
|
);
|
|
99
100
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const operations = mergeOps(oldOperations, newOperations);
|
|
101
|
+
let operations: Operation[] = [];
|
|
102
|
+
// Tx history fetching if xpubOrAddress is not empty
|
|
103
|
+
if (xpubOrAddress) {
|
|
104
|
+
const oldOperations = initialAccount?.operations || [];
|
|
105
|
+
const startAt = oldOperations.length ? (oldOperations[0].blockHeight || 0) + 1 : 0;
|
|
106
|
+
const transactionData = await getOperations(currency, partyId, {
|
|
107
|
+
cursor: startAt,
|
|
108
|
+
limit: 100,
|
|
109
|
+
});
|
|
110
110
|
|
|
111
|
+
const newOperations = filterOperations(transactionData.operations, accountId, partyId);
|
|
112
|
+
operations = mergeOps(oldOperations, newOperations);
|
|
113
|
+
}
|
|
114
|
+
// blockheight retrieval
|
|
115
|
+
const blockHeight = await getLedgerEnd(currency);
|
|
111
116
|
// We return the new account shape
|
|
112
117
|
const shape = {
|
|
113
118
|
id: accountId,
|
|
@@ -1,23 +1,28 @@
|
|
|
1
1
|
import { Balance } from "@ledgerhq/coin-framework/api/types";
|
|
2
2
|
import { getBalance as gatewayGetBalance, type InstrumentBalance } from "../../network/gateway";
|
|
3
3
|
import coinConfig from "../../config";
|
|
4
|
+
import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
4
5
|
|
|
5
|
-
const useGateway = () =>
|
|
6
|
-
|
|
6
|
+
const useGateway = (currency: CryptoCurrency) =>
|
|
7
|
+
coinConfig.getCoinConfig(currency).useGateway === true;
|
|
8
|
+
const getNativeId = (currency: CryptoCurrency) =>
|
|
9
|
+
coinConfig.getCoinConfig(currency).nativeInstrumentId;
|
|
7
10
|
|
|
8
|
-
function adaptInstrument(instrument: InstrumentBalance): Balance {
|
|
11
|
+
function adaptInstrument(currency: CryptoCurrency, instrument: InstrumentBalance): Balance {
|
|
9
12
|
return {
|
|
10
13
|
value: BigInt(instrument.amount),
|
|
11
14
|
locked: instrument.locked === true ? BigInt(instrument.amount) : BigInt(0),
|
|
12
15
|
asset:
|
|
13
|
-
getNativeId() === instrument.instrument_id
|
|
16
|
+
getNativeId(currency) === instrument.instrument_id
|
|
14
17
|
? { type: "native" }
|
|
15
18
|
: { type: "token", assetReference: instrument.instrument_id },
|
|
16
19
|
};
|
|
17
20
|
}
|
|
18
21
|
|
|
19
|
-
export async function getBalance(partyId: string): Promise<Balance[]> {
|
|
20
|
-
if (useGateway())
|
|
21
|
-
return (await gatewayGetBalance(partyId)).map(instrument =>
|
|
22
|
+
export async function getBalance(currency: CryptoCurrency, partyId: string): Promise<Balance[]> {
|
|
23
|
+
if (useGateway(currency))
|
|
24
|
+
return (await gatewayGetBalance(currency, partyId)).map(instrument =>
|
|
25
|
+
adaptInstrument(currency, instrument),
|
|
26
|
+
);
|
|
22
27
|
else throw new Error("Not implemented");
|
|
23
28
|
}
|
|
@@ -2,6 +2,11 @@ import { getBalance as getBalanceFromNetwork } from "../../network/gateway";
|
|
|
2
2
|
import * as coinConfigModule from "../../config";
|
|
3
3
|
import { getBalance } from "./getBalance";
|
|
4
4
|
import { Balance } from "@ledgerhq/coin-framework/api/types";
|
|
5
|
+
import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
6
|
+
|
|
7
|
+
const mockCurrency = {
|
|
8
|
+
id: "canton_network",
|
|
9
|
+
} as unknown as CryptoCurrency;
|
|
5
10
|
|
|
6
11
|
jest.mock("../../network/gateway", () => ({
|
|
7
12
|
getBalance: jest.fn(),
|
|
@@ -35,9 +40,9 @@ describe("getBalance", () => {
|
|
|
35
40
|
|
|
36
41
|
(getBalanceFromNetwork as jest.Mock).mockResolvedValue(mockInstruments);
|
|
37
42
|
|
|
38
|
-
const result = await getBalance("party-id");
|
|
43
|
+
const result = await getBalance(mockCurrency, "party-id");
|
|
39
44
|
|
|
40
|
-
expect(getBalanceFromNetwork).toHaveBeenCalledWith("party-id");
|
|
45
|
+
expect(getBalanceFromNetwork).toHaveBeenCalledWith(mockCurrency, "party-id");
|
|
41
46
|
expect(result).toEqual<Balance[]>([
|
|
42
47
|
{
|
|
43
48
|
value: BigInt(1000),
|
|
@@ -57,7 +62,7 @@ describe("getBalance", () => {
|
|
|
57
62
|
useGateway: false,
|
|
58
63
|
} as any);
|
|
59
64
|
|
|
60
|
-
await expect(getBalance("party-id")).rejects.toThrow("Not implemented");
|
|
65
|
+
await expect(getBalance(mockCurrency, "party-id")).rejects.toThrow("Not implemented");
|
|
61
66
|
expect(getBalanceFromNetwork).not.toHaveBeenCalled();
|
|
62
67
|
});
|
|
63
68
|
});
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { lastBlock } from "./lastBlock";
|
|
2
2
|
import { getLedgerEnd as gatewayGetLedgerEnd } from "../../network/gateway";
|
|
3
3
|
import { getLedgerEnd as nodeGetLedgerEnd } from "../../network/node";
|
|
4
|
+
import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
4
5
|
|
|
5
6
|
jest.mock("../../network/gateway", () => ({
|
|
6
7
|
getLedgerEnd: jest.fn(),
|
|
@@ -18,6 +19,10 @@ jest.mock("../../config", () => ({
|
|
|
18
19
|
|
|
19
20
|
import coinConfig from "../../config";
|
|
20
21
|
|
|
22
|
+
const mockCurrency = {
|
|
23
|
+
id: "canton_network",
|
|
24
|
+
} as unknown as CryptoCurrency;
|
|
25
|
+
|
|
21
26
|
describe("lastBlock", () => {
|
|
22
27
|
beforeEach(() => {
|
|
23
28
|
jest.clearAllMocks();
|
|
@@ -27,7 +32,7 @@ describe("lastBlock", () => {
|
|
|
27
32
|
(coinConfig.getCoinConfig as jest.Mock).mockReturnValue({ useGateway: true });
|
|
28
33
|
(gatewayGetLedgerEnd as jest.Mock).mockResolvedValue(100);
|
|
29
34
|
|
|
30
|
-
const result = await lastBlock();
|
|
35
|
+
const result = await lastBlock(mockCurrency);
|
|
31
36
|
|
|
32
37
|
expect(result).toEqual({ height: 100 });
|
|
33
38
|
expect(gatewayGetLedgerEnd).toHaveBeenCalledTimes(1);
|
|
@@ -38,7 +43,7 @@ describe("lastBlock", () => {
|
|
|
38
43
|
(coinConfig.getCoinConfig as jest.Mock).mockReturnValue({ useGateway: false });
|
|
39
44
|
(nodeGetLedgerEnd as jest.Mock).mockResolvedValue(200);
|
|
40
45
|
|
|
41
|
-
const result = await lastBlock();
|
|
46
|
+
const result = await lastBlock(mockCurrency);
|
|
42
47
|
|
|
43
48
|
expect(result).toEqual({ height: 200 });
|
|
44
49
|
expect(nodeGetLedgerEnd).toHaveBeenCalledTimes(1);
|
|
@@ -2,11 +2,13 @@ import type { BlockInfo } from "@ledgerhq/coin-framework/api/index";
|
|
|
2
2
|
import { getLedgerEnd as nodeGetLedgerEnd } from "../../network/node";
|
|
3
3
|
import { getLedgerEnd } from "../../network/gateway";
|
|
4
4
|
import coinConfig from "../../config";
|
|
5
|
+
import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
5
6
|
|
|
6
|
-
const useGateway = () =>
|
|
7
|
+
const useGateway = (currency: CryptoCurrency) =>
|
|
8
|
+
coinConfig.getCoinConfig(currency).useGateway === true;
|
|
7
9
|
|
|
8
|
-
export async function lastBlock(): Promise<BlockInfo> {
|
|
10
|
+
export async function lastBlock(currency: CryptoCurrency): Promise<BlockInfo> {
|
|
9
11
|
return {
|
|
10
|
-
height: useGateway() ? await getLedgerEnd() : await nodeGetLedgerEnd(),
|
|
12
|
+
height: useGateway(currency) ? await getLedgerEnd(currency) : await nodeGetLedgerEnd(),
|
|
11
13
|
};
|
|
12
14
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Operation, Pagination } from "@ledgerhq/coin-framework/api/index";
|
|
2
2
|
import { getOperations } from "../../network/gateway";
|
|
3
|
-
import
|
|
3
|
+
import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Returns list of operations associated to an account.
|
|
@@ -10,10 +10,11 @@ import coinConfig from "../../config";
|
|
|
10
10
|
* Impl to finalize when backend is ready
|
|
11
11
|
*/
|
|
12
12
|
export async function listOperations(
|
|
13
|
+
currency: CryptoCurrency,
|
|
13
14
|
partyId: string,
|
|
14
15
|
page: Pagination,
|
|
15
16
|
): Promise<[Operation[], string]> {
|
|
16
|
-
const { operations, next } = await getOperations(partyId, {
|
|
17
|
+
const { operations, next } = await getOperations(currency, partyId, {
|
|
17
18
|
cursor: page.pagingToken !== undefined ? parseInt(page.pagingToken) : undefined,
|
|
18
19
|
minOffset: page.minHeight,
|
|
19
20
|
limit: page.limit,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { submit } from "../../network/gateway";
|
|
2
2
|
import * as coinConfigModule from "../../config";
|
|
3
3
|
import { broadcast } from "./broadcast";
|
|
4
|
+
import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
4
5
|
|
|
5
6
|
jest.mock("../../network/gateway", () => ({
|
|
6
7
|
submit: jest.fn(),
|
|
@@ -11,6 +12,10 @@ const mockSerialized = JSON.stringify({
|
|
|
11
12
|
signature: "signature__PARTY__alice:123",
|
|
12
13
|
});
|
|
13
14
|
|
|
15
|
+
const mockCurrency = {
|
|
16
|
+
id: "canton_network",
|
|
17
|
+
} as unknown as CryptoCurrency;
|
|
18
|
+
|
|
14
19
|
describe("broadcast", () => {
|
|
15
20
|
const mockGetCoinConfig = jest.spyOn(coinConfigModule.default, "getCoinConfig");
|
|
16
21
|
|
|
@@ -25,9 +30,9 @@ describe("broadcast", () => {
|
|
|
25
30
|
|
|
26
31
|
(submit as jest.Mock).mockResolvedValue({ update_id: "my-update-id" });
|
|
27
32
|
|
|
28
|
-
const result = await broadcast(mockSerialized);
|
|
33
|
+
const result = await broadcast(mockCurrency, mockSerialized);
|
|
29
34
|
|
|
30
|
-
expect(submit).toHaveBeenCalledWith("alice:123", "serialized-tx", "signature");
|
|
35
|
+
expect(submit).toHaveBeenCalledWith(mockCurrency, "alice:123", "serialized-tx", "signature");
|
|
31
36
|
expect(result).toEqual("my-update-id");
|
|
32
37
|
});
|
|
33
38
|
|
|
@@ -36,7 +41,7 @@ describe("broadcast", () => {
|
|
|
36
41
|
useGateway: false,
|
|
37
42
|
} as any);
|
|
38
43
|
|
|
39
|
-
await expect(broadcast(mockSerialized)).rejects.toThrow("Not implemented");
|
|
44
|
+
await expect(broadcast(mockCurrency, mockSerialized)).rejects.toThrow("Not implemented");
|
|
40
45
|
expect(submit).not.toHaveBeenCalled();
|
|
41
46
|
});
|
|
42
47
|
});
|
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import coinConfig from "../../config";
|
|
2
2
|
import { submit } from "../../network/gateway";
|
|
3
|
+
import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
3
4
|
|
|
4
|
-
const useGateway = () =>
|
|
5
|
+
const useGateway = (currency: CryptoCurrency) =>
|
|
6
|
+
coinConfig.getCoinConfig(currency).useGateway === true;
|
|
5
7
|
|
|
6
|
-
export async function broadcast(signedTx: string): Promise<string> {
|
|
8
|
+
export async function broadcast(currency: CryptoCurrency, signedTx: string): Promise<string> {
|
|
7
9
|
const parsed: { serialized: string; signature: string } = JSON.parse(signedTx);
|
|
8
10
|
const [sig, party] = parsed.signature.split("__PARTY__");
|
|
9
|
-
if (useGateway())
|
|
11
|
+
if (useGateway(currency))
|
|
12
|
+
return (await submit(currency, party, parsed.serialized, sig)).update_id;
|
|
10
13
|
else throw new Error("Not implemented");
|
|
11
14
|
}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
1
|
import BigNumber from "bignumber.js";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
PrepareTransferRequest,
|
|
4
|
+
prepareTransferRequest,
|
|
5
|
+
PrepareTransferResponse,
|
|
6
|
+
} from "../../network/gateway";
|
|
7
|
+
import { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
|
3
8
|
|
|
4
9
|
export async function craftTransaction(
|
|
10
|
+
currency: CryptoCurrency,
|
|
5
11
|
account: {
|
|
6
12
|
address: string;
|
|
7
13
|
nextSequenceNumber?: number;
|
|
@@ -12,19 +18,30 @@ export async function craftTransaction(
|
|
|
12
18
|
amount: BigNumber;
|
|
13
19
|
tokenId: string;
|
|
14
20
|
expireInSeconds: number;
|
|
21
|
+
memo?: string;
|
|
15
22
|
},
|
|
16
23
|
): Promise<{
|
|
17
24
|
nativeTransaction: PrepareTransferResponse;
|
|
18
25
|
serializedTransaction: string;
|
|
19
26
|
hash: string;
|
|
20
27
|
}> {
|
|
21
|
-
const
|
|
28
|
+
const params: PrepareTransferRequest = {
|
|
22
29
|
recipient: transaction.recipient || "",
|
|
23
|
-
amount: transaction.amount.
|
|
24
|
-
type: "token-transfer-request",
|
|
30
|
+
amount: transaction.amount.toString(),
|
|
31
|
+
type: "token-transfer-request" as const,
|
|
25
32
|
execute_before_secs: transaction.expireInSeconds,
|
|
26
33
|
instrument_id: transaction.tokenId,
|
|
27
|
-
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
if (transaction.memo) {
|
|
37
|
+
params.reason = transaction.memo;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const { serialized, json, hash } = await prepareTransferRequest(
|
|
41
|
+
currency,
|
|
42
|
+
account.address,
|
|
43
|
+
params,
|
|
44
|
+
);
|
|
28
45
|
|
|
29
46
|
return {
|
|
30
47
|
nativeTransaction: json,
|