@ledgerhq/coin-solana 0.12.0 → 0.12.1
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 +2 -2
- package/CHANGELOG.md +14 -0
- package/lib/api/chain/index.js +15 -20
- package/lib/api/chain/index.js.map +1 -1
- package/lib/api/chain/program/parser.js +20 -5
- package/lib/api/chain/program/parser.js.map +1 -1
- package/lib/api/chain/stake-activation/rpc.js +40 -51
- package/lib/api/chain/stake-activation/rpc.js.map +1 -1
- package/lib/api/chain/web3.js +136 -211
- package/lib/api/chain/web3.js.map +1 -1
- package/lib/api/traced.js +1 -1
- package/lib/api/traced.js.map +1 -1
- package/lib/bridge/bridge.js +14 -24
- package/lib/bridge/bridge.js.map +1 -1
- package/lib/bridge/js.js +3 -3
- package/lib/bridge/js.js.map +1 -1
- package/lib/bridge.integration.test.js +133 -65
- package/lib/bridge.integration.test.js.map +1 -1
- package/lib/broadcast.js +3 -12
- package/lib/broadcast.js.map +1 -1
- package/lib/buildTransaction.js +33 -46
- package/lib/buildTransaction.js.map +1 -1
- package/lib/cli-transaction.js +50 -27
- package/lib/cli-transaction.js.map +1 -1
- package/lib/estimateMaxSpendable.js +11 -21
- package/lib/estimateMaxSpendable.js.map +1 -1
- package/lib/getTransactionStatus.js +2 -11
- package/lib/getTransactionStatus.js.map +1 -1
- package/lib/hw-getAddress.js +3 -12
- package/lib/hw-getAddress.js.map +1 -1
- package/lib/logic.js +3 -5
- package/lib/logic.js.map +1 -1
- package/lib/preload.js +20 -33
- package/lib/preload.js.map +1 -1
- package/lib/prepareTransaction.js +354 -382
- package/lib/prepareTransaction.js.map +1 -1
- package/lib/signOperation.js +98 -26
- package/lib/signOperation.js.map +1 -1
- package/lib/specs.js +11 -20
- package/lib/specs.js.map +1 -1
- package/lib/speculos-deviceActions.js +48 -72
- package/lib/speculos-deviceActions.js.map +1 -1
- package/lib/synchronization.js +66 -76
- package/lib/synchronization.js.map +1 -1
- package/lib/transaction.js +10 -2
- package/lib/transaction.js.map +1 -1
- package/lib/tx-fees.js +97 -76
- package/lib/tx-fees.js.map +1 -1
- package/lib/utils.js +16 -49
- package/lib/utils.js.map +1 -1
- package/lib/validator-app/index.js +26 -38
- package/lib/validator-app/index.js.map +1 -1
- package/lib-es/api/chain/index.js +15 -20
- package/lib-es/api/chain/index.js.map +1 -1
- package/lib-es/api/chain/program/parser.js +20 -5
- package/lib-es/api/chain/program/parser.js.map +1 -1
- package/lib-es/api/chain/stake-activation/rpc.js +40 -51
- package/lib-es/api/chain/stake-activation/rpc.js.map +1 -1
- package/lib-es/api/chain/web3.js +152 -227
- package/lib-es/api/chain/web3.js.map +1 -1
- package/lib-es/api/traced.js +1 -1
- package/lib-es/api/traced.js.map +1 -1
- package/lib-es/bridge/bridge.js +14 -24
- package/lib-es/bridge/bridge.js.map +1 -1
- package/lib-es/bridge/js.js +3 -3
- package/lib-es/bridge/js.js.map +1 -1
- package/lib-es/bridge.integration.test.js +133 -65
- package/lib-es/bridge.integration.test.js.map +1 -1
- package/lib-es/broadcast.js +3 -12
- package/lib-es/broadcast.js.map +1 -1
- package/lib-es/buildTransaction.js +33 -46
- package/lib-es/buildTransaction.js.map +1 -1
- package/lib-es/cli-transaction.js +50 -27
- package/lib-es/cli-transaction.js.map +1 -1
- package/lib-es/estimateMaxSpendable.js +11 -21
- package/lib-es/estimateMaxSpendable.js.map +1 -1
- package/lib-es/getTransactionStatus.js +2 -11
- package/lib-es/getTransactionStatus.js.map +1 -1
- package/lib-es/hw-getAddress.js +3 -12
- package/lib-es/hw-getAddress.js.map +1 -1
- package/lib-es/logic.js +3 -5
- package/lib-es/logic.js.map +1 -1
- package/lib-es/preload.js +20 -33
- package/lib-es/preload.js.map +1 -1
- package/lib-es/prepareTransaction.js +354 -382
- package/lib-es/prepareTransaction.js.map +1 -1
- package/lib-es/signOperation.js +98 -26
- package/lib-es/signOperation.js.map +1 -1
- package/lib-es/specs.js +11 -20
- package/lib-es/specs.js.map +1 -1
- package/lib-es/speculos-deviceActions.js +48 -72
- package/lib-es/speculos-deviceActions.js.map +1 -1
- package/lib-es/synchronization.js +66 -76
- package/lib-es/synchronization.js.map +1 -1
- package/lib-es/transaction.js +10 -2
- package/lib-es/transaction.js.map +1 -1
- package/lib-es/tx-fees.js +97 -76
- package/lib-es/tx-fees.js.map +1 -1
- package/lib-es/utils.js +16 -49
- package/lib-es/utils.js.map +1 -1
- package/lib-es/validator-app/index.js +26 -38
- package/lib-es/validator-app/index.js.map +1 -1
- package/package.json +3 -3
- package/tsconfig.json +3 -3
|
@@ -1,13 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
3
|
exports.prepareTransaction = void 0;
|
|
13
4
|
const cryptoassets_1 = require("@ledgerhq/cryptoassets");
|
|
@@ -19,52 +10,53 @@ const logic_1 = require("./logic");
|
|
|
19
10
|
const utils_1 = require("./utils");
|
|
20
11
|
const jsHelpers_1 = require("@ledgerhq/coin-framework/bridge/jsHelpers");
|
|
21
12
|
const estimateMaxSpendable_1 = require("./estimateMaxSpendable");
|
|
22
|
-
function deriveCommandDescriptor(mainAccount, tx, api) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
});
|
|
13
|
+
async function deriveCommandDescriptor(mainAccount, tx, api) {
|
|
14
|
+
const { model } = tx;
|
|
15
|
+
switch (model.kind) {
|
|
16
|
+
case "transfer":
|
|
17
|
+
return deriveTransferCommandDescriptor(mainAccount, tx, model, api);
|
|
18
|
+
case "token.transfer":
|
|
19
|
+
return deriveTokenTransferCommandDescriptor(mainAccount, tx, model, api);
|
|
20
|
+
case "token.createATA":
|
|
21
|
+
return deriveCreateAssociatedTokenAccountCommandDescriptor(mainAccount, tx, model, api);
|
|
22
|
+
case "stake.createAccount":
|
|
23
|
+
return deriveStakeCreateAccountCommandDescriptor(mainAccount, tx, model, api);
|
|
24
|
+
case "stake.delegate":
|
|
25
|
+
return deriveStakeDelegateCommandDescriptor(mainAccount, tx, model, api);
|
|
26
|
+
case "stake.undelegate":
|
|
27
|
+
return deriveStakeUndelegateCommandDescriptor(mainAccount, tx, model, api);
|
|
28
|
+
case "stake.withdraw":
|
|
29
|
+
return deriveStakeWithdrawCommandDescriptor(mainAccount, tx, model, api);
|
|
30
|
+
case "stake.split":
|
|
31
|
+
return deriveStakeSplitCommandDescriptor(mainAccount, tx, model, api);
|
|
32
|
+
default:
|
|
33
|
+
return (0, utils_1.assertUnreachable)(model);
|
|
34
|
+
}
|
|
46
35
|
}
|
|
47
|
-
const prepareTransaction = (mainAccount, tx, api) =>
|
|
36
|
+
const prepareTransaction = async (mainAccount, tx, api) => {
|
|
48
37
|
const txToDeriveFrom = updateModelIfSubAccountIdPresent(tx);
|
|
49
|
-
const commandDescriptor =
|
|
50
|
-
const model =
|
|
38
|
+
const commandDescriptor = await deriveCommandDescriptor(mainAccount, txToDeriveFrom, api);
|
|
39
|
+
const model = {
|
|
40
|
+
...tx.model,
|
|
41
|
+
commandDescriptor,
|
|
42
|
+
};
|
|
51
43
|
const patch = {
|
|
52
44
|
model,
|
|
53
45
|
};
|
|
54
46
|
return (0, jsHelpers_1.updateTransaction)(tx, patch);
|
|
55
|
-
}
|
|
47
|
+
};
|
|
56
48
|
exports.prepareTransaction = prepareTransaction;
|
|
57
|
-
const deriveTokenTransferCommandDescriptor = (mainAccount, tx, model, api) =>
|
|
49
|
+
const deriveTokenTransferCommandDescriptor = async (mainAccount, tx, model, api) => {
|
|
58
50
|
const errors = {};
|
|
59
51
|
const warnings = {};
|
|
60
52
|
const subAccount = (0, index_1.findSubAccountById)(mainAccount, model.uiState.subAccountId);
|
|
61
53
|
if (!subAccount || subAccount.type !== "TokenAccount") {
|
|
62
54
|
throw new Error("subaccount not found");
|
|
63
55
|
}
|
|
64
|
-
if (
|
|
56
|
+
if (subAccount?.state === "frozen") {
|
|
65
57
|
errors.amount = new errors_2.SolanaTokenAccountFrozen();
|
|
66
58
|
}
|
|
67
|
-
|
|
59
|
+
await validateRecipientCommon(mainAccount, tx, errors, warnings, api, true);
|
|
68
60
|
const memo = model.uiState.memo;
|
|
69
61
|
if (typeof memo === "string" && memo.length > 0) {
|
|
70
62
|
validateMemoCommon(memo, errors);
|
|
@@ -82,7 +74,7 @@ const deriveTokenTransferCommandDescriptor = (mainAccount, tx, model, api) => __
|
|
|
82
74
|
};
|
|
83
75
|
const recipientDescriptorOrError = errors.recipient
|
|
84
76
|
? defaultRecipientDescriptor
|
|
85
|
-
:
|
|
77
|
+
: await getTokenRecipient(tx.recipient, mintAddress, api);
|
|
86
78
|
if (!errors.recipient && recipientDescriptorOrError instanceof Error) {
|
|
87
79
|
errors.recipient = recipientDescriptorOrError;
|
|
88
80
|
}
|
|
@@ -90,12 +82,12 @@ const deriveTokenTransferCommandDescriptor = (mainAccount, tx, model, api) => __
|
|
|
90
82
|
? defaultRecipientDescriptor
|
|
91
83
|
: recipientDescriptorOrError;
|
|
92
84
|
const assocAccRentExempt = recipientDescriptor.shouldCreateAsAssociatedTokenAccount
|
|
93
|
-
?
|
|
85
|
+
? await api.getAssocTokenAccMinNativeBalance()
|
|
94
86
|
: 0;
|
|
95
87
|
if (recipientDescriptor.shouldCreateAsAssociatedTokenAccount) {
|
|
96
88
|
warnings.recipient = new errors_2.SolanaRecipientAssociatedTokenAccountWillBeFunded();
|
|
97
89
|
}
|
|
98
|
-
const { fee, spendable: spendableSol } =
|
|
90
|
+
const { fee, spendable: spendableSol } = await (0, estimateMaxSpendable_1.estimateFeeAndSpendable)(api, mainAccount, tx);
|
|
99
91
|
if (spendableSol.lt(assocAccRentExempt) || spendableSol.isZero()) {
|
|
100
92
|
errors.fee = new errors_1.NotEnoughBalance();
|
|
101
93
|
}
|
|
@@ -121,370 +113,353 @@ const deriveTokenTransferCommandDescriptor = (mainAccount, tx, model, api) => __
|
|
|
121
113
|
warnings,
|
|
122
114
|
errors,
|
|
123
115
|
};
|
|
124
|
-
}
|
|
125
|
-
function getTokenRecipient(recipientAddress, mintAddress, api) {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if (
|
|
132
|
-
|
|
133
|
-
return new errors_2.SolanaAddressOffEd25519();
|
|
134
|
-
}
|
|
135
|
-
const recipientAssociatedTokenAccountAddress = yield api.findAssocTokenAccAddress(recipientAddress, mintAddress);
|
|
136
|
-
const shouldCreateAsAssociatedTokenAccount = !(yield isAccountFunded(recipientAssociatedTokenAccountAddress, api));
|
|
137
|
-
if (!shouldCreateAsAssociatedTokenAccount) {
|
|
138
|
-
const associatedTokenAccount = yield (0, web3_1.getMaybeTokenAccount)(recipientAssociatedTokenAccountAddress, api);
|
|
139
|
-
if (associatedTokenAccount instanceof Error)
|
|
140
|
-
throw recipientTokenAccount;
|
|
141
|
-
if ((associatedTokenAccount === null || associatedTokenAccount === void 0 ? void 0 : associatedTokenAccount.state) === "frozen") {
|
|
142
|
-
return new errors_2.SolanaTokenAccountFrozen();
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
return {
|
|
146
|
-
walletAddress: recipientAddress,
|
|
147
|
-
shouldCreateAsAssociatedTokenAccount,
|
|
148
|
-
tokenAccAddress: recipientAssociatedTokenAccountAddress,
|
|
149
|
-
};
|
|
116
|
+
};
|
|
117
|
+
async function getTokenRecipient(recipientAddress, mintAddress, api) {
|
|
118
|
+
const recipientTokenAccount = await (0, web3_1.getMaybeTokenAccount)(recipientAddress, api);
|
|
119
|
+
if (recipientTokenAccount instanceof Error) {
|
|
120
|
+
throw recipientTokenAccount;
|
|
121
|
+
}
|
|
122
|
+
if (recipientTokenAccount === undefined) {
|
|
123
|
+
if (!(0, logic_1.isEd25519Address)(recipientAddress)) {
|
|
124
|
+
return new errors_2.SolanaAddressOffEd25519();
|
|
150
125
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (
|
|
126
|
+
const recipientAssociatedTokenAccountAddress = await api.findAssocTokenAccAddress(recipientAddress, mintAddress);
|
|
127
|
+
const shouldCreateAsAssociatedTokenAccount = !(await isAccountFunded(recipientAssociatedTokenAccountAddress, api));
|
|
128
|
+
if (!shouldCreateAsAssociatedTokenAccount) {
|
|
129
|
+
const associatedTokenAccount = await (0, web3_1.getMaybeTokenAccount)(recipientAssociatedTokenAccountAddress, api);
|
|
130
|
+
if (associatedTokenAccount instanceof Error)
|
|
131
|
+
throw recipientTokenAccount;
|
|
132
|
+
if (associatedTokenAccount?.state === "frozen") {
|
|
156
133
|
return new errors_2.SolanaTokenAccountFrozen();
|
|
157
134
|
}
|
|
158
|
-
if (recipientTokenAccount.state !== "initialized") {
|
|
159
|
-
return new errors_2.SolanaTokenAccounNotInitialized();
|
|
160
|
-
}
|
|
161
135
|
}
|
|
162
136
|
return {
|
|
163
|
-
walletAddress:
|
|
164
|
-
shouldCreateAsAssociatedTokenAccount
|
|
165
|
-
tokenAccAddress:
|
|
137
|
+
walletAddress: recipientAddress,
|
|
138
|
+
shouldCreateAsAssociatedTokenAccount,
|
|
139
|
+
tokenAccAddress: recipientAssociatedTokenAccountAddress,
|
|
166
140
|
};
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
const errors = {};
|
|
172
|
-
const token = (0, cryptoassets_1.getTokenById)(model.uiState.tokenId);
|
|
173
|
-
const mint = token.contractAddress;
|
|
174
|
-
const associatedTokenAccountAddress = yield api.findAssocTokenAccAddress(mainAccount.freshAddress, mint);
|
|
175
|
-
const { fee } = yield (0, estimateMaxSpendable_1.estimateFeeAndSpendable)(api, mainAccount, tx);
|
|
176
|
-
if (mainAccount.spendableBalance.lt(fee)) {
|
|
177
|
-
errors.fee = new errors_1.NotEnoughBalance();
|
|
178
|
-
}
|
|
179
|
-
return {
|
|
180
|
-
fee,
|
|
181
|
-
command: {
|
|
182
|
-
kind: model.kind,
|
|
183
|
-
mint: mint,
|
|
184
|
-
owner: mainAccount.freshAddress,
|
|
185
|
-
associatedTokenAccountAddress,
|
|
186
|
-
},
|
|
187
|
-
warnings: {},
|
|
188
|
-
errors,
|
|
189
|
-
};
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
function deriveTransferCommandDescriptor(mainAccount, tx, model, api) {
|
|
193
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
194
|
-
const errors = {};
|
|
195
|
-
const warnings = {};
|
|
196
|
-
yield validateRecipientCommon(mainAccount, tx, errors, warnings, api, false);
|
|
197
|
-
const memo = model.uiState.memo;
|
|
198
|
-
if (typeof memo === "string" && memo.length > 0) {
|
|
199
|
-
validateMemoCommon(memo, errors);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
if (recipientTokenAccount.mint.toBase58() !== mintAddress) {
|
|
144
|
+
return new errors_2.SolanaTokenAccountHoldsAnotherToken();
|
|
200
145
|
}
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
if (tx.useAllAmount) {
|
|
204
|
-
if (txAmount.eq(0)) {
|
|
205
|
-
errors.amount = new errors_1.NotEnoughBalance();
|
|
206
|
-
}
|
|
146
|
+
if (recipientTokenAccount.state === "frozen") {
|
|
147
|
+
return new errors_2.SolanaTokenAccountFrozen();
|
|
207
148
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
errors.amount = new errors_1.AmountRequired();
|
|
211
|
-
}
|
|
212
|
-
else if (txAmount.gt(spendable)) {
|
|
213
|
-
errors.amount = new errors_1.NotEnoughBalance();
|
|
214
|
-
}
|
|
149
|
+
if (recipientTokenAccount.state !== "initialized") {
|
|
150
|
+
return new errors_2.SolanaTokenAccounNotInitialized();
|
|
215
151
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
};
|
|
223
|
-
return {
|
|
224
|
-
command,
|
|
225
|
-
fee,
|
|
226
|
-
warnings,
|
|
227
|
-
errors,
|
|
228
|
-
};
|
|
229
|
-
});
|
|
152
|
+
}
|
|
153
|
+
return {
|
|
154
|
+
walletAddress: recipientTokenAccount.owner.toBase58(),
|
|
155
|
+
shouldCreateAsAssociatedTokenAccount: false,
|
|
156
|
+
tokenAccAddress: recipientAddress,
|
|
157
|
+
};
|
|
230
158
|
}
|
|
231
|
-
function
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
159
|
+
async function deriveCreateAssociatedTokenAccountCommandDescriptor(mainAccount, tx, model, api) {
|
|
160
|
+
const errors = {};
|
|
161
|
+
const token = (0, cryptoassets_1.getTokenById)(model.uiState.tokenId);
|
|
162
|
+
const mint = token.contractAddress;
|
|
163
|
+
const associatedTokenAccountAddress = await api.findAssocTokenAccAddress(mainAccount.freshAddress, mint);
|
|
164
|
+
const { fee } = await (0, estimateMaxSpendable_1.estimateFeeAndSpendable)(api, mainAccount, tx);
|
|
165
|
+
if (mainAccount.spendableBalance.lt(fee)) {
|
|
166
|
+
errors.fee = new errors_1.NotEnoughBalance();
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
fee,
|
|
170
|
+
command: {
|
|
171
|
+
kind: model.kind,
|
|
172
|
+
mint: mint,
|
|
173
|
+
owner: mainAccount.freshAddress,
|
|
174
|
+
associatedTokenAccountAddress,
|
|
175
|
+
},
|
|
176
|
+
warnings: {},
|
|
177
|
+
errors,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
async function deriveTransferCommandDescriptor(mainAccount, tx, model, api) {
|
|
181
|
+
const errors = {};
|
|
182
|
+
const warnings = {};
|
|
183
|
+
await validateRecipientCommon(mainAccount, tx, errors, warnings, api, false);
|
|
184
|
+
const memo = model.uiState.memo;
|
|
185
|
+
if (typeof memo === "string" && memo.length > 0) {
|
|
186
|
+
validateMemoCommon(memo, errors);
|
|
187
|
+
}
|
|
188
|
+
const { fee, spendable } = await (0, estimateMaxSpendable_1.estimateFeeAndSpendable)(api, mainAccount, tx);
|
|
189
|
+
const txAmount = tx.useAllAmount ? spendable : tx.amount;
|
|
190
|
+
if (tx.useAllAmount) {
|
|
191
|
+
if (txAmount.eq(0)) {
|
|
192
|
+
errors.amount = new errors_1.NotEnoughBalance();
|
|
241
193
|
}
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
else if (txAmount.gt(spendable)) {
|
|
247
|
-
errors.amount = new errors_1.NotEnoughBalance();
|
|
248
|
-
}
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
if (txAmount.lte(0)) {
|
|
197
|
+
errors.amount = new errors_1.AmountRequired();
|
|
249
198
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
},
|
|
268
|
-
fee,
|
|
269
|
-
warnings,
|
|
270
|
-
errors,
|
|
271
|
-
};
|
|
272
|
-
});
|
|
199
|
+
else if (txAmount.gt(spendable)) {
|
|
200
|
+
errors.amount = new errors_1.NotEnoughBalance();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
const command = {
|
|
204
|
+
kind: "transfer",
|
|
205
|
+
amount: txAmount.toNumber(),
|
|
206
|
+
sender: mainAccount.freshAddress,
|
|
207
|
+
recipient: tx.recipient,
|
|
208
|
+
memo: model.uiState.memo,
|
|
209
|
+
};
|
|
210
|
+
return {
|
|
211
|
+
command,
|
|
212
|
+
fee,
|
|
213
|
+
warnings,
|
|
214
|
+
errors,
|
|
215
|
+
};
|
|
273
216
|
}
|
|
274
|
-
function
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
if (
|
|
281
|
-
errors.
|
|
217
|
+
async function deriveStakeCreateAccountCommandDescriptor(mainAccount, tx, model, api) {
|
|
218
|
+
const errors = {};
|
|
219
|
+
const warnings = {};
|
|
220
|
+
const { fee, spendable } = await (0, estimateMaxSpendable_1.estimateFeeAndSpendable)(api, mainAccount, tx);
|
|
221
|
+
const txAmount = tx.useAllAmount ? spendable : tx.amount;
|
|
222
|
+
if (tx.useAllAmount) {
|
|
223
|
+
if (txAmount.eq(0)) {
|
|
224
|
+
errors.amount = new errors_1.NotEnoughBalance();
|
|
282
225
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
case "activating":
|
|
288
|
-
errors.stakeAccAddr = new errors_2.SolanaStakeAccountIsNotDelegatable();
|
|
289
|
-
break;
|
|
290
|
-
case "inactive":
|
|
291
|
-
break;
|
|
292
|
-
case "deactivating":
|
|
293
|
-
if (((_a = stake.delegation) === null || _a === void 0 ? void 0 : _a.voteAccAddr) !== uiState.voteAccAddr) {
|
|
294
|
-
errors.stakeAccAddr = new errors_2.SolanaStakeAccountValidatorIsUnchangeable();
|
|
295
|
-
}
|
|
296
|
-
break;
|
|
297
|
-
default:
|
|
298
|
-
return (0, utils_1.assertUnreachable)(stake.activation.state);
|
|
299
|
-
}
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
if (txAmount.lte(0)) {
|
|
229
|
+
errors.amount = new errors_1.AmountRequired();
|
|
300
230
|
}
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
errors.fee = new errors_1.NotEnoughBalance();
|
|
231
|
+
else if (txAmount.gt(spendable)) {
|
|
232
|
+
errors.amount = new errors_1.NotEnoughBalance();
|
|
304
233
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
fee,
|
|
313
|
-
warnings: {},
|
|
314
|
-
errors,
|
|
315
|
-
};
|
|
234
|
+
}
|
|
235
|
+
const { uiState: { delegate }, } = model;
|
|
236
|
+
await validateValidatorCommon(delegate.voteAccAddress, errors, api);
|
|
237
|
+
const stakeAccAddressSeed = `stake:${Math.random().toString()}`;
|
|
238
|
+
const stakeAccAddress = await (0, web3_1.getStakeAccountAddressWithSeed)({
|
|
239
|
+
fromAddress: mainAccount.freshAddress,
|
|
240
|
+
seed: stakeAccAddressSeed,
|
|
316
241
|
});
|
|
242
|
+
const stakeAccRentExemptAmount = await (0, web3_1.getStakeAccountMinimumBalanceForRentExemption)(api);
|
|
243
|
+
return {
|
|
244
|
+
command: {
|
|
245
|
+
kind: "stake.createAccount",
|
|
246
|
+
amount: txAmount.toNumber(),
|
|
247
|
+
stakeAccRentExemptAmount,
|
|
248
|
+
fromAccAddress: mainAccount.freshAddress,
|
|
249
|
+
stakeAccAddress,
|
|
250
|
+
delegate,
|
|
251
|
+
seed: stakeAccAddressSeed,
|
|
252
|
+
},
|
|
253
|
+
fee,
|
|
254
|
+
warnings,
|
|
255
|
+
errors,
|
|
256
|
+
};
|
|
317
257
|
}
|
|
318
|
-
function
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
errors.fee = new errors_1.NotEnoughBalance();
|
|
258
|
+
async function deriveStakeDelegateCommandDescriptor(mainAccount, tx, model, api) {
|
|
259
|
+
const errors = {};
|
|
260
|
+
const { uiState } = model;
|
|
261
|
+
const stake = validateAndTryGetStakeAccount(mainAccount, uiState.stakeAccAddr, errors);
|
|
262
|
+
if (stake !== undefined && !stake.hasStakeAuth && !stake.hasWithdrawAuth) {
|
|
263
|
+
errors.stakeAccAddr = new errors_2.SolanaStakeNoStakeAuth();
|
|
264
|
+
}
|
|
265
|
+
await validateValidatorCommon(uiState.voteAccAddr, errors, api);
|
|
266
|
+
if (!errors.voteAccAddr && stake !== undefined) {
|
|
267
|
+
switch (stake.activation.state) {
|
|
268
|
+
case "active":
|
|
269
|
+
case "activating":
|
|
270
|
+
errors.stakeAccAddr = new errors_2.SolanaStakeAccountIsNotDelegatable();
|
|
271
|
+
break;
|
|
272
|
+
case "inactive":
|
|
273
|
+
break;
|
|
274
|
+
case "deactivating":
|
|
275
|
+
if (stake.delegation?.voteAccAddr !== uiState.voteAccAddr) {
|
|
276
|
+
errors.stakeAccAddr = new errors_2.SolanaStakeAccountValidatorIsUnchangeable();
|
|
277
|
+
}
|
|
278
|
+
break;
|
|
279
|
+
default:
|
|
280
|
+
return (0, utils_1.assertUnreachable)(stake.activation.state);
|
|
342
281
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
282
|
+
}
|
|
283
|
+
const { fee } = await (0, estimateMaxSpendable_1.estimateFeeAndSpendable)(api, mainAccount, tx);
|
|
284
|
+
if (mainAccount.spendableBalance.lt(fee)) {
|
|
285
|
+
errors.fee = new errors_1.NotEnoughBalance();
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
command: {
|
|
289
|
+
kind: "stake.delegate",
|
|
290
|
+
authorizedAccAddr: mainAccount.freshAddress,
|
|
291
|
+
stakeAccAddr: uiState.stakeAccAddr,
|
|
292
|
+
voteAccAddr: uiState.voteAccAddr,
|
|
293
|
+
},
|
|
294
|
+
fee,
|
|
295
|
+
warnings: {},
|
|
296
|
+
errors,
|
|
297
|
+
};
|
|
354
298
|
}
|
|
355
|
-
function
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
errors.stakeAccAddr = new errors_2.
|
|
367
|
-
|
|
299
|
+
async function deriveStakeUndelegateCommandDescriptor(mainAccount, tx, model, api) {
|
|
300
|
+
const errors = {};
|
|
301
|
+
const { uiState } = model;
|
|
302
|
+
const stake = validateAndTryGetStakeAccount(mainAccount, uiState.stakeAccAddr, errors);
|
|
303
|
+
if (stake !== undefined) {
|
|
304
|
+
switch (stake.activation.state) {
|
|
305
|
+
case "active":
|
|
306
|
+
case "activating":
|
|
307
|
+
break;
|
|
308
|
+
case "inactive":
|
|
309
|
+
case "deactivating":
|
|
310
|
+
errors.stakeAccAddr = new errors_2.SolanaStakeAccountIsNotUndelegatable();
|
|
311
|
+
break;
|
|
312
|
+
default:
|
|
313
|
+
return (0, utils_1.assertUnreachable)(stake.activation.state);
|
|
368
314
|
}
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
errors.fee = new errors_1.NotEnoughBalance();
|
|
315
|
+
if (!errors.stakeAccAddr && !stake.hasStakeAuth && !stake.hasWithdrawAuth) {
|
|
316
|
+
errors.stakeAccAddr = new errors_2.SolanaStakeNoStakeAuth();
|
|
372
317
|
}
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
318
|
+
}
|
|
319
|
+
const { fee } = await (0, estimateMaxSpendable_1.estimateFeeAndSpendable)(api, mainAccount, tx);
|
|
320
|
+
if (mainAccount.solanaResources.unstakeReserve.lt(fee)) {
|
|
321
|
+
errors.fee = new errors_1.NotEnoughBalance();
|
|
322
|
+
}
|
|
323
|
+
return {
|
|
324
|
+
command: {
|
|
325
|
+
kind: "stake.undelegate",
|
|
326
|
+
authorizedAccAddr: mainAccount.freshAddress,
|
|
327
|
+
stakeAccAddr: uiState.stakeAccAddr,
|
|
328
|
+
},
|
|
329
|
+
fee,
|
|
330
|
+
warnings: {},
|
|
331
|
+
errors,
|
|
332
|
+
};
|
|
386
333
|
}
|
|
387
|
-
function
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
if (tx.amount.lte(0)) {
|
|
395
|
-
errors.amount = new errors_1.AmountRequired();
|
|
334
|
+
async function deriveStakeWithdrawCommandDescriptor(mainAccount, tx, model, api) {
|
|
335
|
+
const errors = {};
|
|
336
|
+
const { uiState } = model;
|
|
337
|
+
const stake = validateAndTryGetStakeAccount(mainAccount, uiState.stakeAccAddr, errors);
|
|
338
|
+
if (!errors.stakeAccAddr && stake !== undefined) {
|
|
339
|
+
if (!stake.hasWithdrawAuth) {
|
|
340
|
+
errors.stakeAccAddr = new errors_2.SolanaStakeNoWithdrawAuth();
|
|
396
341
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
errors.stakeAccAddr = new errors_1.InvalidAddress("", {
|
|
400
|
-
currencyName: mainAccount.currency.name,
|
|
401
|
-
});
|
|
342
|
+
else if (stake.withdrawable <= 0) {
|
|
343
|
+
errors.stakeAccAddr = new errors_2.SolanaStakeAccountNothingToWithdraw();
|
|
402
344
|
}
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
345
|
+
}
|
|
346
|
+
const { fee } = await (0, estimateMaxSpendable_1.estimateFeeAndSpendable)(api, mainAccount, tx);
|
|
347
|
+
if (mainAccount.solanaResources.unstakeReserve.lt(fee)) {
|
|
348
|
+
errors.fee = new errors_1.NotEnoughBalance();
|
|
349
|
+
}
|
|
350
|
+
return {
|
|
351
|
+
command: {
|
|
352
|
+
kind: "stake.withdraw",
|
|
353
|
+
authorizedAccAddr: mainAccount.freshAddress,
|
|
354
|
+
stakeAccAddr: uiState.stakeAccAddr,
|
|
355
|
+
amount: stake?.withdrawable ?? 0,
|
|
356
|
+
toAccAddr: mainAccount.freshAddress,
|
|
357
|
+
},
|
|
358
|
+
fee,
|
|
359
|
+
warnings: {},
|
|
360
|
+
errors,
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
async function deriveStakeSplitCommandDescriptor(mainAccount, tx, model, api) {
|
|
364
|
+
const errors = {};
|
|
365
|
+
// TODO: find stake account in the main acc when synced
|
|
366
|
+
const { uiState } = model;
|
|
367
|
+
// TODO: use all amount
|
|
368
|
+
if (tx.amount.lte(0)) {
|
|
369
|
+
errors.amount = new errors_1.AmountRequired();
|
|
370
|
+
}
|
|
371
|
+
// TODO: else if amount > stake balance
|
|
372
|
+
if (!(0, logic_1.isValidBase58Address)(uiState.stakeAccAddr)) {
|
|
373
|
+
errors.stakeAccAddr = new errors_1.InvalidAddress("", {
|
|
374
|
+
currencyName: mainAccount.currency.name,
|
|
409
375
|
});
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
splitStakeAccAddr,
|
|
418
|
-
},
|
|
419
|
-
fee: commandFees,
|
|
420
|
-
warnings: {},
|
|
421
|
-
errors: {},
|
|
422
|
-
};
|
|
376
|
+
}
|
|
377
|
+
mainAccount.solanaResources?.stakes ?? [];
|
|
378
|
+
const commandFees = await (0, web3_1.getStakeAccountMinimumBalanceForRentExemption)(api);
|
|
379
|
+
const splitStakeAccAddrSeed = `stake:${Math.random().toString()}`;
|
|
380
|
+
const splitStakeAccAddr = await (0, web3_1.getStakeAccountAddressWithSeed)({
|
|
381
|
+
fromAddress: mainAccount.freshAddress,
|
|
382
|
+
seed: splitStakeAccAddrSeed,
|
|
423
383
|
});
|
|
384
|
+
return {
|
|
385
|
+
command: {
|
|
386
|
+
kind: "stake.split",
|
|
387
|
+
authorizedAccAddr: mainAccount.freshAddress,
|
|
388
|
+
stakeAccAddr: uiState.stakeAccAddr,
|
|
389
|
+
amount: tx.amount.toNumber(),
|
|
390
|
+
seed: splitStakeAccAddrSeed,
|
|
391
|
+
splitStakeAccAddr,
|
|
392
|
+
},
|
|
393
|
+
fee: commandFees,
|
|
394
|
+
warnings: {},
|
|
395
|
+
errors: {},
|
|
396
|
+
};
|
|
424
397
|
}
|
|
425
398
|
// if subaccountid present - it's a token transfer
|
|
426
399
|
function updateModelIfSubAccountIdPresent(tx) {
|
|
427
400
|
if (tx.subAccountId) {
|
|
428
|
-
return
|
|
401
|
+
return {
|
|
402
|
+
...tx,
|
|
403
|
+
model: {
|
|
429
404
|
kind: "token.transfer",
|
|
430
|
-
uiState:
|
|
431
|
-
|
|
405
|
+
uiState: {
|
|
406
|
+
...tx.model.uiState,
|
|
407
|
+
subAccountId: tx.subAccountId,
|
|
408
|
+
},
|
|
409
|
+
},
|
|
410
|
+
};
|
|
432
411
|
}
|
|
433
412
|
return tx;
|
|
434
413
|
}
|
|
435
|
-
function isAccountFunded(address, api) {
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
return balance > 0;
|
|
439
|
-
});
|
|
414
|
+
async function isAccountFunded(address, api) {
|
|
415
|
+
const balance = await api.getBalance(address);
|
|
416
|
+
return balance > 0;
|
|
440
417
|
}
|
|
441
|
-
function validateRecipientCommon(mainAccount, tx, errors, warnings, api, allowATA) {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
418
|
+
async function validateRecipientCommon(mainAccount, tx, errors, warnings, api, allowATA) {
|
|
419
|
+
if (!tx.recipient) {
|
|
420
|
+
errors.recipient = new errors_1.RecipientRequired();
|
|
421
|
+
}
|
|
422
|
+
else if (mainAccount.freshAddress === tx.recipient) {
|
|
423
|
+
errors.recipient = new errors_1.InvalidAddressBecauseDestinationIsAlsoSource();
|
|
424
|
+
}
|
|
425
|
+
else if (!(0, logic_1.isValidBase58Address)(tx.recipient)) {
|
|
426
|
+
errors.recipient = new errors_1.InvalidAddress("", {
|
|
427
|
+
currencyName: mainAccount.currency.name,
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
else {
|
|
431
|
+
const recipientWalletIsUnfunded = !(await isAccountFunded(tx.recipient, api));
|
|
432
|
+
const recipientTokenAccount = await (0, web3_1.getMaybeTokenAccount)(tx.recipient, api);
|
|
433
|
+
if (recipientTokenAccount instanceof Error) {
|
|
434
|
+
throw recipientTokenAccount;
|
|
453
435
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
throw recipientTokenAccount;
|
|
459
|
-
}
|
|
460
|
-
if (recipientTokenAccount) {
|
|
461
|
-
if (allowATA) {
|
|
462
|
-
if ((0, logic_1.isEd25519Address)(tx.recipient)) {
|
|
463
|
-
errors.recipient = new errors_2.SolanaTokenAccountNotAllowed();
|
|
464
|
-
}
|
|
465
|
-
else {
|
|
466
|
-
warnings.recipient = new errors_2.SolanaTokenAccountWarning();
|
|
467
|
-
}
|
|
436
|
+
if (recipientTokenAccount) {
|
|
437
|
+
if (allowATA) {
|
|
438
|
+
if ((0, logic_1.isEd25519Address)(tx.recipient)) {
|
|
439
|
+
errors.recipient = new errors_2.SolanaTokenAccountNotAllowed();
|
|
468
440
|
}
|
|
469
441
|
else {
|
|
470
|
-
|
|
442
|
+
warnings.recipient = new errors_2.SolanaTokenAccountWarning();
|
|
471
443
|
}
|
|
472
444
|
}
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
throw recipientTokenAccount;
|
|
476
|
-
}
|
|
477
|
-
if (mintTokenAccount) {
|
|
478
|
-
errors.recipient = new errors_2.SolanaMintAccountNotAllowed();
|
|
479
|
-
}
|
|
480
|
-
if (recipientWalletIsUnfunded) {
|
|
481
|
-
warnings.recipient = new errors_2.SolanaAccountNotFunded();
|
|
482
|
-
}
|
|
483
|
-
if (!(0, logic_1.isEd25519Address)(tx.recipient)) {
|
|
484
|
-
warnings.recipientOffCurve = new errors_2.SolanaAddressOffEd25519();
|
|
445
|
+
else {
|
|
446
|
+
errors.recipient = new errors_2.SolanaTokenAccountNotAllowed();
|
|
485
447
|
}
|
|
486
448
|
}
|
|
487
|
-
|
|
449
|
+
const mintTokenAccount = await (0, web3_1.getMaybeMintAccount)(tx.recipient, api);
|
|
450
|
+
if (mintTokenAccount instanceof Error) {
|
|
451
|
+
throw recipientTokenAccount;
|
|
452
|
+
}
|
|
453
|
+
if (mintTokenAccount) {
|
|
454
|
+
errors.recipient = new errors_2.SolanaMintAccountNotAllowed();
|
|
455
|
+
}
|
|
456
|
+
if (recipientWalletIsUnfunded) {
|
|
457
|
+
warnings.recipient = new errors_2.SolanaAccountNotFunded();
|
|
458
|
+
}
|
|
459
|
+
if (!(0, logic_1.isEd25519Address)(tx.recipient)) {
|
|
460
|
+
warnings.recipientOffCurve = new errors_2.SolanaAddressOffEd25519();
|
|
461
|
+
}
|
|
462
|
+
}
|
|
488
463
|
}
|
|
489
464
|
function validateMemoCommon(memo, errors) {
|
|
490
465
|
const memoBytes = Buffer.from(memo, "utf-8");
|
|
@@ -496,26 +471,23 @@ function validateMemoCommon(memo, errors) {
|
|
|
496
471
|
errors.transaction = errors.memo;
|
|
497
472
|
}
|
|
498
473
|
}
|
|
499
|
-
function validateValidatorCommon(addr, errors, api) {
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
errors.voteAccAddr = new errors_2.SolanaInvalidValidator();
|
|
513
|
-
}
|
|
474
|
+
async function validateValidatorCommon(addr, errors, api) {
|
|
475
|
+
if (addr.length === 0) {
|
|
476
|
+
errors.voteAccAddr = new errors_2.SolanaValidatorRequired();
|
|
477
|
+
}
|
|
478
|
+
else if (!(0, logic_1.isValidBase58Address)(addr)) {
|
|
479
|
+
errors.voteAccAddr = new errors_1.InvalidAddress("", {
|
|
480
|
+
currencyName: "Solana",
|
|
481
|
+
});
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
const voteAcc = await (0, web3_1.getMaybeVoteAccount)(addr, api);
|
|
485
|
+
if (voteAcc instanceof Error || voteAcc === undefined) {
|
|
486
|
+
errors.voteAccAddr = new errors_2.SolanaInvalidValidator();
|
|
514
487
|
}
|
|
515
|
-
}
|
|
488
|
+
}
|
|
516
489
|
}
|
|
517
490
|
function validateAndTryGetStakeAccount(account, stakeAccAddr, errors) {
|
|
518
|
-
var _a;
|
|
519
491
|
if (stakeAccAddr.length === 0) {
|
|
520
492
|
errors.stakeAccAddr = new errors_2.SolanaStakeAccountRequired();
|
|
521
493
|
}
|
|
@@ -525,7 +497,7 @@ function validateAndTryGetStakeAccount(account, stakeAccAddr, errors) {
|
|
|
525
497
|
});
|
|
526
498
|
}
|
|
527
499
|
if (!errors.stakeAccAddr) {
|
|
528
|
-
const stake =
|
|
500
|
+
const stake = account.solanaResources?.stakes.find(stake => stake.stakeAccAddr === stakeAccAddr);
|
|
529
501
|
if (stake === undefined) {
|
|
530
502
|
errors.stakeAccAddr = new errors_2.SolanaStakeAccountNotFound();
|
|
531
503
|
}
|