@ledgerhq/coin-algorand 0.2.1 → 0.2.2-next.0
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/.eslintrc.js +8 -46
- package/CHANGELOG.md +13 -0
- package/package.json +10 -20
- package/src/account.ts +6 -18
- package/src/api/index.ts +2 -9
- package/src/api/indexer.ts +6 -15
- package/src/bridge/js.ts +4 -7
- package/src/bridge.integration.test.ts +29 -47
- package/src/buildTransaction.ts +7 -15
- package/src/cli-transaction.ts +6 -16
- package/src/deviceTransactionConfig.ts +4 -13
- package/src/errors.ts +1 -1
- package/src/js-broadcast.ts +2 -8
- package/src/js-estimateMaxSpendable.ts +2 -4
- package/src/js-getFeesForTransaction.ts +2 -7
- package/src/js-getTransactionStatus.ts +6 -20
- package/src/js-prepareTransaction.ts +2 -8
- package/src/js-signOperation.ts +11 -27
- package/src/js-synchronization.ts +25 -48
- package/src/logic.ts +3 -5
- package/src/mock.ts +3 -3
- package/src/serialization.ts +4 -13
- package/src/specs.ts +35 -72
- package/src/speculos-deviceActions.ts +93 -95
- package/src/transaction.ts +5 -21
- package/tsconfig.json +2 -8
package/.eslintrc.js
CHANGED
|
@@ -1,57 +1,19 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
parser: "@typescript-eslint/parser",
|
|
3
2
|
env: {
|
|
4
3
|
browser: true,
|
|
5
4
|
es6: true,
|
|
6
|
-
node: true,
|
|
7
|
-
jest: true,
|
|
8
5
|
},
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
overrides: [
|
|
7
|
+
{
|
|
8
|
+
files: ["src/**/*.test.{ts,tsx}"],
|
|
9
|
+
env: {
|
|
10
|
+
"jest/globals": true,
|
|
11
|
+
},
|
|
12
|
+
plugins: ["jest"],
|
|
13
|
+
},
|
|
14
14
|
],
|
|
15
|
-
globals: {
|
|
16
|
-
Atomics: "readonly",
|
|
17
|
-
SharedArrayBuffer: "readonly",
|
|
18
|
-
},
|
|
19
|
-
plugins: ["@typescript-eslint", "prettier"],
|
|
20
15
|
rules: {
|
|
21
16
|
"no-console": ["error", { allow: ["warn", "error"] }],
|
|
22
|
-
"linebreak-style": ["error", "unix"],
|
|
23
|
-
semi: ["error", "always"],
|
|
24
|
-
"no-unused-vars": "off",
|
|
25
|
-
"import/prefer-default-export": 0,
|
|
26
|
-
"no-plusplus": 0,
|
|
27
|
-
"no-underscore-dangle": 0,
|
|
28
|
-
"prefer-template": 0,
|
|
29
|
-
"no-await-in-loop": 0,
|
|
30
|
-
"no-restricted-syntax": 0,
|
|
31
|
-
"consistent-return": 0,
|
|
32
|
-
"no-lonely-if": 0,
|
|
33
|
-
"no-use-before-define": 0,
|
|
34
|
-
"no-nested-ternary": 0,
|
|
35
|
-
"import/no-cycle": 0,
|
|
36
|
-
"no-multi-assign": 0,
|
|
37
|
-
"guard-for-in": 0,
|
|
38
|
-
"no-continue": 0,
|
|
39
|
-
"lines-between-class-members": 0,
|
|
40
|
-
"prefer-destructuring": 0,
|
|
41
|
-
"prettier/prettier": "error",
|
|
42
|
-
"@typescript-eslint/no-use-before-define": "off",
|
|
43
|
-
"@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }],
|
|
44
17
|
"@typescript-eslint/no-empty-function": "off",
|
|
45
|
-
"@typescript-eslint/no-namespace": ["error", { allowDeclarations: true }],
|
|
46
|
-
"@typescript-eslint/no-explicit-any": 0,
|
|
47
|
-
"@typescript-eslint/ban-types": [
|
|
48
|
-
"error",
|
|
49
|
-
{
|
|
50
|
-
extendDefaults: true,
|
|
51
|
-
types: {
|
|
52
|
-
"{}": false,
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
],
|
|
56
18
|
},
|
|
57
19
|
};
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @ledgerhq/coin-algorand
|
|
2
2
|
|
|
3
|
+
## 0.2.2-next.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [[`9adc1862dd`](https://github.com/LedgerHQ/ledger-live/commit/9adc1862dda605a722d19f3b6895bd324834c914), [`4a1454beb3`](https://github.com/LedgerHQ/ledger-live/commit/4a1454beb3f86405ba2686e07879c12a7d35ad8e), [`809065c571`](https://github.com/LedgerHQ/ledger-live/commit/809065c57198646a49adea112b9d799e35a57d25), [`d1aa522db7`](https://github.com/LedgerHQ/ledger-live/commit/d1aa522db75f7ea850efe412abaa4dc7d37af6b7), [`ebe5b07afe`](https://github.com/LedgerHQ/ledger-live/commit/ebe5b07afec441ea3e2d9103da9e1175972add47)]:
|
|
8
|
+
- @ledgerhq/errors@6.12.7-next.0
|
|
9
|
+
- @ledgerhq/cryptoassets@9.8.0-next.0
|
|
10
|
+
- @ledgerhq/types-cryptoassets@7.2.1-next.0
|
|
11
|
+
- @ledgerhq/types-live@6.35.1-next.0
|
|
12
|
+
- @ledgerhq/coin-framework@0.3.6-next.0
|
|
13
|
+
- @ledgerhq/devices@8.0.4-next.0
|
|
14
|
+
- @ledgerhq/hw-app-algorand@6.27.16-next.0
|
|
15
|
+
|
|
3
16
|
## 0.2.1
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ledgerhq/coin-algorand",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2-next.0",
|
|
4
4
|
"description": "Ledger Algorand Coin integration",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Ledger",
|
|
@@ -52,32 +52,22 @@
|
|
|
52
52
|
"lodash": "^4.17.21",
|
|
53
53
|
"prando": "^6.0.1",
|
|
54
54
|
"rxjs": "^6.6.7",
|
|
55
|
-
"@ledgerhq/coin-framework": "^0.3.
|
|
56
|
-
"@ledgerhq/cryptoassets": "^9.
|
|
57
|
-
"@ledgerhq/devices": "^8.0.
|
|
58
|
-
"@ledgerhq/errors": "^6.12.
|
|
59
|
-
"@ledgerhq/hw-app-algorand": "^6.27.
|
|
55
|
+
"@ledgerhq/coin-framework": "^0.3.6-next.0",
|
|
56
|
+
"@ledgerhq/cryptoassets": "^9.8.0-next.0",
|
|
57
|
+
"@ledgerhq/devices": "^8.0.4-next.0",
|
|
58
|
+
"@ledgerhq/errors": "^6.12.7-next.0",
|
|
59
|
+
"@ledgerhq/hw-app-algorand": "^6.27.16-next.0",
|
|
60
60
|
"@ledgerhq/live-env": "^0.3.0",
|
|
61
61
|
"@ledgerhq/live-promise": "^0.0.1",
|
|
62
|
-
"@ledgerhq/types-cryptoassets": "^7.2.0",
|
|
63
|
-
"@ledgerhq/types-live": "^6.35.0"
|
|
62
|
+
"@ledgerhq/types-cryptoassets": "^7.2.1-next.0",
|
|
63
|
+
"@ledgerhq/types-live": "^6.35.1-next.0"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@types/invariant": "^2.2.2",
|
|
67
67
|
"@types/jest": "^29.2.4",
|
|
68
68
|
"@types/lodash": "^4.14.191",
|
|
69
|
-
"@typescript-eslint/eslint-plugin": "^5.46.1",
|
|
70
|
-
"@typescript-eslint/parser": "^5.46.1",
|
|
71
|
-
"eslint": "^7.32.0",
|
|
72
|
-
"eslint-config-prettier": "^8.3.0",
|
|
73
|
-
"eslint-config-typescript": "^3.0.0",
|
|
74
|
-
"eslint-formatter-pretty": "^3.0.1",
|
|
75
|
-
"eslint-plugin-prettier": "^3.4.0",
|
|
76
|
-
"eslint-plugin-typescript": "^0.14.0",
|
|
77
69
|
"jest": "^28.1.1",
|
|
78
|
-
"
|
|
79
|
-
"ts-jest": "^28.0.5",
|
|
80
|
-
"typescript": "^4.9.5"
|
|
70
|
+
"ts-jest": "^28.0.5"
|
|
81
71
|
},
|
|
82
72
|
"scripts": {
|
|
83
73
|
"clean": "rimraf lib lib-es",
|
|
@@ -85,7 +75,7 @@
|
|
|
85
75
|
"prewatch": "pnpm build",
|
|
86
76
|
"watch": "tsc --watch",
|
|
87
77
|
"doc": "documentation readme src/** --section=API --pe ts --re ts --re d.ts",
|
|
88
|
-
"lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx",
|
|
78
|
+
"lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx --cache",
|
|
89
79
|
"lint:fix": "pnpm lint --fix",
|
|
90
80
|
"test": "jest"
|
|
91
81
|
}
|
package/src/account.ts
CHANGED
|
@@ -6,10 +6,7 @@ import { BigNumber } from "bignumber.js";
|
|
|
6
6
|
import invariant from "invariant";
|
|
7
7
|
import type { AlgorandAccount, AlgorandResources } from "./types";
|
|
8
8
|
|
|
9
|
-
function formatOperationSpecifics(
|
|
10
|
-
op: Operation,
|
|
11
|
-
unit: Unit | null | undefined
|
|
12
|
-
): string {
|
|
9
|
+
function formatOperationSpecifics(op: Operation, unit: Unit | null | undefined): string {
|
|
13
10
|
const { rewards } = op.extra;
|
|
14
11
|
return rewards
|
|
15
12
|
? " REWARDS : " +
|
|
@@ -34,34 +31,25 @@ function formatAccountSpecifics(account: Account): string {
|
|
|
34
31
|
showCode: true,
|
|
35
32
|
};
|
|
36
33
|
let str = " ";
|
|
37
|
-
str +=
|
|
38
|
-
formatCurrencyUnit(unit, account.spendableBalance, formatConfig) +
|
|
39
|
-
" spendable. ";
|
|
34
|
+
str += formatCurrencyUnit(unit, account.spendableBalance, formatConfig) + " spendable. ";
|
|
40
35
|
|
|
41
36
|
if ((algorandResources as AlgorandResources).rewards.gt(0)) {
|
|
42
37
|
str +=
|
|
43
|
-
formatCurrencyUnit(
|
|
44
|
-
|
|
45
|
-
(algorandResources as AlgorandResources).rewards,
|
|
46
|
-
formatConfig
|
|
47
|
-
) + " rewards. ";
|
|
38
|
+
formatCurrencyUnit(unit, (algorandResources as AlgorandResources).rewards, formatConfig) +
|
|
39
|
+
" rewards. ";
|
|
48
40
|
}
|
|
49
41
|
|
|
50
42
|
return str;
|
|
51
43
|
}
|
|
52
44
|
|
|
53
|
-
export function fromOperationExtraRaw(
|
|
54
|
-
extra: Record<string, any> | null | undefined
|
|
55
|
-
) {
|
|
45
|
+
export function fromOperationExtraRaw(extra: Record<string, any> | null | undefined) {
|
|
56
46
|
if (extra && extra.rewards) {
|
|
57
47
|
return { ...extra, rewards: new BigNumber(extra.rewards) };
|
|
58
48
|
}
|
|
59
49
|
|
|
60
50
|
return extra;
|
|
61
51
|
}
|
|
62
|
-
export function toOperationExtraRaw(
|
|
63
|
-
extra: Record<string, any> | null | undefined
|
|
64
|
-
) {
|
|
52
|
+
export function toOperationExtraRaw(extra: Record<string, any> | null | undefined) {
|
|
65
53
|
if (extra && extra.rewards) {
|
|
66
54
|
return { ...extra, rewards: extra.rewards.toString() };
|
|
67
55
|
}
|
package/src/api/index.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { NetworkRequestCall } from "@ledgerhq/coin-framework/network";
|
|
2
2
|
import { AlgoAccount, AlgoTransactionParams } from "./algodv2.types";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
broadcastTransaction,
|
|
6
|
-
getAccount,
|
|
7
|
-
getTransactionParams,
|
|
8
|
-
} from "./algodv2";
|
|
4
|
+
import { broadcastTransaction, getAccount, getTransactionParams } from "./algodv2";
|
|
9
5
|
|
|
10
6
|
import { getAccountTransactions } from "./indexer";
|
|
11
7
|
import { AlgoTransaction } from "./indexer.types";
|
|
@@ -32,10 +28,7 @@ export class AlgorandAPI {
|
|
|
32
28
|
return broadcastTransaction(this.network)(payload);
|
|
33
29
|
}
|
|
34
30
|
|
|
35
|
-
async getAccountTransactions(
|
|
36
|
-
address: string,
|
|
37
|
-
startAt?: number
|
|
38
|
-
): Promise<AlgoTransaction[]> {
|
|
31
|
+
async getAccountTransactions(address: string, startAt?: number): Promise<AlgoTransaction[]> {
|
|
39
32
|
return getAccountTransactions(this.network)(address, startAt);
|
|
40
33
|
}
|
|
41
34
|
}
|
package/src/api/indexer.ts
CHANGED
|
@@ -13,8 +13,7 @@ const LIMIT = 100; // Max nb of transactions per request
|
|
|
13
13
|
const BASE_URL = getEnv("API_ALGORAND_BLOCKCHAIN_EXPLORER_API_ENDPOINT");
|
|
14
14
|
const INDEXER_URL = `${BASE_URL}/idx2/v2`;
|
|
15
15
|
|
|
16
|
-
const fullUrl = (route: string): string =>
|
|
17
|
-
`${INDEXER_URL}${route}?limit=${LIMIT}`;
|
|
16
|
+
const fullUrl = (route: string): string => `${INDEXER_URL}${route}?limit=${LIMIT}`;
|
|
18
17
|
|
|
19
18
|
export const getAccountTransactions =
|
|
20
19
|
(network: NetworkRequestCall) =>
|
|
@@ -42,7 +41,7 @@ export const getAccountTransactions =
|
|
|
42
41
|
// @ts-ignore
|
|
43
42
|
nextToken = data["next-token"];
|
|
44
43
|
newRawTxs = data.transactions;
|
|
45
|
-
newRawTxs.map(parseRawTransaction).forEach(
|
|
44
|
+
newRawTxs.map(parseRawTransaction).forEach(tx => mergedTxs.push(tx));
|
|
46
45
|
} while (newRawTxs.length >= LIMIT);
|
|
47
46
|
|
|
48
47
|
return mergedTxs;
|
|
@@ -56,9 +55,7 @@ const parseRawTransaction = (tx: any): AlgoTransaction => {
|
|
|
56
55
|
amount: new BigNumber(info.amount),
|
|
57
56
|
recipientAddress: info.receiver,
|
|
58
57
|
closeAmount:
|
|
59
|
-
info["close-amount"] === undefined
|
|
60
|
-
? undefined
|
|
61
|
-
: new BigNumber(info["close-amount"]),
|
|
58
|
+
info["close-amount"] === undefined ? undefined : new BigNumber(info["close-amount"]),
|
|
62
59
|
closeToAddress: info["close-remainder-to"],
|
|
63
60
|
};
|
|
64
61
|
details = paymentInfo;
|
|
@@ -70,9 +67,7 @@ const parseRawTransaction = (tx: any): AlgoTransaction => {
|
|
|
70
67
|
assetRecipientAddress: info.receiver,
|
|
71
68
|
assetSenderAddress: info.sender,
|
|
72
69
|
assetCloseAmount:
|
|
73
|
-
info["close-amount"] === undefined
|
|
74
|
-
? undefined
|
|
75
|
-
: new BigNumber(info["close-amount"]),
|
|
70
|
+
info["close-amount"] === undefined ? undefined : new BigNumber(info["close-amount"]),
|
|
76
71
|
assetCloseToAddress: tx["close-to"],
|
|
77
72
|
};
|
|
78
73
|
details = assetTransferInfo;
|
|
@@ -86,13 +81,9 @@ const parseRawTransaction = (tx: any): AlgoTransaction => {
|
|
|
86
81
|
senderRewards: new BigNumber(tx["sender-rewards"]),
|
|
87
82
|
recipientRewards: new BigNumber(tx["receiver-rewards"]),
|
|
88
83
|
closeRewards:
|
|
89
|
-
tx["close-rewards"] === undefined
|
|
90
|
-
? undefined
|
|
91
|
-
: new BigNumber(tx["close-rewards"]),
|
|
84
|
+
tx["close-rewards"] === undefined ? undefined : new BigNumber(tx["close-rewards"]),
|
|
92
85
|
closeAmount:
|
|
93
|
-
tx["closing-amount"] === undefined
|
|
94
|
-
? undefined
|
|
95
|
-
: new BigNumber(tx["closing-amount"]),
|
|
86
|
+
tx["closing-amount"] === undefined ? undefined : new BigNumber(tx["closing-amount"]),
|
|
96
87
|
fee: new BigNumber(tx.fee),
|
|
97
88
|
note: tx.note,
|
|
98
89
|
|
package/src/bridge/js.ts
CHANGED
|
@@ -28,7 +28,7 @@ const updateTransaction = (t: Transaction, patch: Partial<Transaction>) => ({
|
|
|
28
28
|
|
|
29
29
|
export function buildCurrencyBridge(
|
|
30
30
|
deviceCommunication: DeviceCommunication,
|
|
31
|
-
network: NetworkRequestCall
|
|
31
|
+
network: NetworkRequestCall,
|
|
32
32
|
): CurrencyBridge {
|
|
33
33
|
const algorandAPI = new AlgorandAPI(network);
|
|
34
34
|
|
|
@@ -48,14 +48,11 @@ export function buildCurrencyBridge(
|
|
|
48
48
|
|
|
49
49
|
export function buildAccountBridge(
|
|
50
50
|
deviceCommunication: DeviceCommunication,
|
|
51
|
-
network: NetworkRequestCall
|
|
51
|
+
network: NetworkRequestCall,
|
|
52
52
|
): AccountBridge<Transaction> {
|
|
53
53
|
const algorandAPI = new AlgorandAPI(network);
|
|
54
54
|
|
|
55
|
-
const receive = makeAccountBridgeReceive(
|
|
56
|
-
getAddressWrapper(getAddress),
|
|
57
|
-
deviceCommunication
|
|
58
|
-
);
|
|
55
|
+
const receive = makeAccountBridgeReceive(getAddressWrapper(getAddress), deviceCommunication);
|
|
59
56
|
const signOperation = buildSignOperation(deviceCommunication, algorandAPI);
|
|
60
57
|
const getAccountShape = makeGetAccountShape(algorandAPI);
|
|
61
58
|
const sync = makeSync({ getAccountShape });
|
|
@@ -83,7 +80,7 @@ export function buildAccountBridge(
|
|
|
83
80
|
export function createBridges(
|
|
84
81
|
deviceCommunication: DeviceCommunication,
|
|
85
82
|
network: NetworkRequestCall,
|
|
86
|
-
_cacheFn: unknown
|
|
83
|
+
_cacheFn: unknown,
|
|
87
84
|
) {
|
|
88
85
|
return {
|
|
89
86
|
currencyBridge: buildCurrencyBridge(deviceCommunication, network),
|
|
@@ -39,19 +39,16 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
39
39
|
// Rewards issues
|
|
40
40
|
raw: {
|
|
41
41
|
id: "js:2:algorand:c8b672d16c497bb097a48f09a9cccf0c4c7d6391acb7a4e7cd3f236fadbef9c4:",
|
|
42
|
-
seedIdentifier:
|
|
43
|
-
"c8b672d16c497bb097a48f09a9cccf0c4c7d6391acb7a4e7cd3f236fadbef9c4",
|
|
42
|
+
seedIdentifier: "c8b672d16c497bb097a48f09a9cccf0c4c7d6391acb7a4e7cd3f236fadbef9c4",
|
|
44
43
|
name: "Algorand 1",
|
|
45
44
|
xpub: "c8b672d16c497bb097a48f09a9cccf0c4c7d6391acb7a4e7cd3f236fadbef9c4",
|
|
46
45
|
derivationMode: "",
|
|
47
46
|
index: 0,
|
|
48
|
-
freshAddress:
|
|
49
|
-
"ZC3HFULMJF53BF5ER4E2TTGPBRGH2Y4RVS32JZ6NH4RW7LN67HCE6UBS3Q",
|
|
47
|
+
freshAddress: "ZC3HFULMJF53BF5ER4E2TTGPBRGH2Y4RVS32JZ6NH4RW7LN67HCE6UBS3Q",
|
|
50
48
|
freshAddressPath: "44'/283'/0'/0/0",
|
|
51
49
|
freshAddresses: [
|
|
52
50
|
{
|
|
53
|
-
address:
|
|
54
|
-
"ZC3HFULMJF53BF5ER4E2TTGPBRGH2Y4RVS32JZ6NH4RW7LN67HCE6UBS3Q",
|
|
51
|
+
address: "ZC3HFULMJF53BF5ER4E2TTGPBRGH2Y4RVS32JZ6NH4RW7LN67HCE6UBS3Q",
|
|
55
52
|
derivationPath: "44'/283'/0'/0/0",
|
|
56
53
|
},
|
|
57
54
|
],
|
|
@@ -68,11 +65,10 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
68
65
|
transactions: [
|
|
69
66
|
{
|
|
70
67
|
name: "Same as Recipient",
|
|
71
|
-
transaction:
|
|
68
|
+
transaction: t => ({
|
|
72
69
|
...t,
|
|
73
70
|
amount: new BigNumber(100),
|
|
74
|
-
recipient:
|
|
75
|
-
"ZC3HFULMJF53BF5ER4E2TTGPBRGH2Y4RVS32JZ6NH4RW7LN67HCE6UBS3Q",
|
|
71
|
+
recipient: "ZC3HFULMJF53BF5ER4E2TTGPBRGH2Y4RVS32JZ6NH4RW7LN67HCE6UBS3Q",
|
|
76
72
|
}),
|
|
77
73
|
expectedStatus: {
|
|
78
74
|
errors: {
|
|
@@ -83,11 +79,10 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
83
79
|
},
|
|
84
80
|
{
|
|
85
81
|
name: "Account creation minimum amount too low",
|
|
86
|
-
transaction:
|
|
82
|
+
transaction: t => ({
|
|
87
83
|
...t,
|
|
88
84
|
amount: new BigNumber("100"),
|
|
89
|
-
recipient:
|
|
90
|
-
"MVE6C3XB4JBKXKORC3NLAWFW4M7EY3MADU6L72DADFP4NZBJIAYXGSLN3Y",
|
|
85
|
+
recipient: "MVE6C3XB4JBKXKORC3NLAWFW4M7EY3MADU6L72DADFP4NZBJIAYXGSLN3Y",
|
|
91
86
|
}),
|
|
92
87
|
expectedStatus: {
|
|
93
88
|
errors: {
|
|
@@ -98,11 +93,10 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
98
93
|
},
|
|
99
94
|
{
|
|
100
95
|
name: "send",
|
|
101
|
-
transaction:
|
|
96
|
+
transaction: t => ({
|
|
102
97
|
...t,
|
|
103
98
|
amount: new BigNumber("1000"),
|
|
104
|
-
recipient:
|
|
105
|
-
"MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
99
|
+
recipient: "MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
106
100
|
}),
|
|
107
101
|
expectedStatus: {
|
|
108
102
|
errors: {},
|
|
@@ -114,8 +108,7 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
114
108
|
transaction: (t, account) => ({
|
|
115
109
|
...t,
|
|
116
110
|
amount: account.balance,
|
|
117
|
-
recipient:
|
|
118
|
-
"MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
111
|
+
recipient: "MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
119
112
|
}),
|
|
120
113
|
expectedStatus: {
|
|
121
114
|
errors: {
|
|
@@ -129,8 +122,7 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
129
122
|
transaction: (t, account) => ({
|
|
130
123
|
...t,
|
|
131
124
|
amount: account.balance.minus("100"),
|
|
132
|
-
recipient:
|
|
133
|
-
"MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
125
|
+
recipient: "MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
134
126
|
}),
|
|
135
127
|
expectedStatus: {
|
|
136
128
|
errors: {
|
|
@@ -141,13 +133,12 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
141
133
|
},
|
|
142
134
|
{
|
|
143
135
|
name: "optIn",
|
|
144
|
-
transaction:
|
|
136
|
+
transaction: t => ({
|
|
145
137
|
...t,
|
|
146
138
|
mode: "optIn",
|
|
147
139
|
assetId: "algorand/asa/31231",
|
|
148
140
|
amount: new BigNumber("1000"),
|
|
149
|
-
recipient:
|
|
150
|
-
"ZC3HFULMJF53BF5ER4E2TTGPBRGH2Y4RVS32JZ6NH4RW7LN67HCE6UBS3Q",
|
|
141
|
+
recipient: "ZC3HFULMJF53BF5ER4E2TTGPBRGH2Y4RVS32JZ6NH4RW7LN67HCE6UBS3Q",
|
|
151
142
|
}),
|
|
152
143
|
expectedStatus: {
|
|
153
144
|
errors: {},
|
|
@@ -157,13 +148,12 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
157
148
|
},
|
|
158
149
|
{
|
|
159
150
|
name: "Can't send ASA to an address that didn't Opt-in",
|
|
160
|
-
transaction:
|
|
151
|
+
transaction: t => ({
|
|
161
152
|
...t,
|
|
162
153
|
subAccountId:
|
|
163
154
|
"js:2:algorand:ZC3HFULMJF53BF5ER4E2TTGPBRGH2Y4RVS32JZ6NH4RW7LN67HCE6UBS3Q:+312769",
|
|
164
155
|
amount: new BigNumber("1000"),
|
|
165
|
-
recipient:
|
|
166
|
-
"ZQVVJ2S4XWS542KXBBVIINOEHIDOEZKZWK725PWFNN2I5RNCUBI53RT2EY",
|
|
156
|
+
recipient: "ZQVVJ2S4XWS542KXBBVIINOEHIDOEZKZWK725PWFNN2I5RNCUBI53RT2EY",
|
|
167
157
|
}),
|
|
168
158
|
expectedStatus: {
|
|
169
159
|
errors: {
|
|
@@ -174,13 +164,12 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
174
164
|
},
|
|
175
165
|
{
|
|
176
166
|
name: "send Token",
|
|
177
|
-
transaction:
|
|
167
|
+
transaction: t => ({
|
|
178
168
|
...t,
|
|
179
169
|
subAccountId:
|
|
180
170
|
"js:2:algorand:ZC3HFULMJF53BF5ER4E2TTGPBRGH2Y4RVS32JZ6NH4RW7LN67HCE6UBS3Q:+312769",
|
|
181
171
|
amount: new BigNumber("1000"),
|
|
182
|
-
recipient:
|
|
183
|
-
"MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
172
|
+
recipient: "MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
184
173
|
}),
|
|
185
174
|
expectedStatus: {
|
|
186
175
|
errors: {},
|
|
@@ -190,13 +179,12 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
190
179
|
},
|
|
191
180
|
{
|
|
192
181
|
name: "send Token - more than available",
|
|
193
|
-
transaction:
|
|
182
|
+
transaction: t => ({
|
|
194
183
|
...t,
|
|
195
184
|
subAccountId:
|
|
196
185
|
"js:2:algorand:ZC3HFULMJF53BF5ER4E2TTGPBRGH2Y4RVS32JZ6NH4RW7LN67HCE6UBS3Q:+312769",
|
|
197
186
|
amount: new BigNumber("100000000000"),
|
|
198
|
-
recipient:
|
|
199
|
-
"MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
187
|
+
recipient: "MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
200
188
|
}),
|
|
201
189
|
expectedStatus: {
|
|
202
190
|
errors: {
|
|
@@ -207,10 +195,9 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
207
195
|
},
|
|
208
196
|
{
|
|
209
197
|
name: "send max",
|
|
210
|
-
transaction:
|
|
198
|
+
transaction: t => ({
|
|
211
199
|
...t,
|
|
212
|
-
recipient:
|
|
213
|
-
"MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
200
|
+
recipient: "MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
214
201
|
useAllAmount: true,
|
|
215
202
|
}),
|
|
216
203
|
expectedStatus: (account, _, status) => {
|
|
@@ -226,19 +213,16 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
226
213
|
{
|
|
227
214
|
raw: {
|
|
228
215
|
id: "js:2:algorand:MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI:",
|
|
229
|
-
seedIdentifier:
|
|
230
|
-
"c8b672d16c497bb097a48f09a9cccf0c4c7d6391acb7a4e7cd3f236fadbef9c4",
|
|
216
|
+
seedIdentifier: "c8b672d16c497bb097a48f09a9cccf0c4c7d6391acb7a4e7cd3f236fadbef9c4",
|
|
231
217
|
xpub: "6104eb314f51f4db5733976bd8c066297019ebaa6adcf39b4aa318d553c571cc",
|
|
232
218
|
name: "Algorand 4",
|
|
233
219
|
derivationMode: "",
|
|
234
220
|
index: 3,
|
|
235
|
-
freshAddress:
|
|
236
|
-
"MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
221
|
+
freshAddress: "MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
237
222
|
freshAddressPath: "44'/283'/3'/0/0",
|
|
238
223
|
freshAddresses: [
|
|
239
224
|
{
|
|
240
|
-
address:
|
|
241
|
-
"MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
225
|
+
address: "MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI",
|
|
242
226
|
derivationPath: "44'/283'/3'/0/0",
|
|
243
227
|
},
|
|
244
228
|
],
|
|
@@ -254,11 +238,10 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
254
238
|
transactions: [
|
|
255
239
|
{
|
|
256
240
|
name: "Can't send funds if balance too low",
|
|
257
|
-
transaction:
|
|
241
|
+
transaction: t => ({
|
|
258
242
|
...t,
|
|
259
243
|
amount: new BigNumber("1000"),
|
|
260
|
-
recipient:
|
|
261
|
-
"YWZPDCL5XQPCPGBXKB7KAG7YF2QGCGEX37YTSM55CPEPHKNE2ZSKRAXNQ4",
|
|
244
|
+
recipient: "YWZPDCL5XQPCPGBXKB7KAG7YF2QGCGEX37YTSM55CPEPHKNE2ZSKRAXNQ4",
|
|
262
245
|
}),
|
|
263
246
|
expectedStatus: {
|
|
264
247
|
errors: {},
|
|
@@ -267,13 +250,12 @@ const algorand: CurrenciesData<Transaction> = {
|
|
|
267
250
|
},
|
|
268
251
|
{
|
|
269
252
|
name: "Can't send ASA if Algo balance too low",
|
|
270
|
-
transaction:
|
|
253
|
+
transaction: t => ({
|
|
271
254
|
...t,
|
|
272
255
|
subAccountId:
|
|
273
256
|
"js:2:algorand:MECOWMKPKH2NWVZTS5V5RQDGFFYBT25KNLOPHG2KUMMNKU6FOHGJT24WBI:+312769",
|
|
274
257
|
amount: new BigNumber("1000000"),
|
|
275
|
-
recipient:
|
|
276
|
-
"YWZPDCL5XQPCPGBXKB7KAG7YF2QGCGEX37YTSM55CPEPHKNE2ZSKRAXNQ4",
|
|
258
|
+
recipient: "YWZPDCL5XQPCPGBXKB7KAG7YF2QGCGEX37YTSM55CPEPHKNE2ZSKRAXNQ4",
|
|
277
259
|
}),
|
|
278
260
|
expectedStatus: {
|
|
279
261
|
errors: {
|
|
@@ -296,7 +278,7 @@ export const dataset: DatasetTest<AlgorandTransaction> = {
|
|
|
296
278
|
|
|
297
279
|
describe("Algorand bridge", () => {
|
|
298
280
|
test.todo(
|
|
299
|
-
"This is an empty test to make jest command pass. Remove it once there is a real test."
|
|
281
|
+
"This is an empty test to make jest command pass. Remove it once there is a real test.",
|
|
300
282
|
);
|
|
301
283
|
});
|
|
302
284
|
|
package/src/buildTransaction.ts
CHANGED
|
@@ -16,15 +16,10 @@ import type { Transaction } from "./types";
|
|
|
16
16
|
|
|
17
17
|
export const buildTransactionPayload =
|
|
18
18
|
(algorandAPI: AlgorandAPI) =>
|
|
19
|
-
async (
|
|
20
|
-
|
|
21
|
-
transaction: Transaction
|
|
22
|
-
): Promise<AlgoTransactionPayload> => {
|
|
23
|
-
const { amount, recipient, mode, memo, assetId, subAccountId } =
|
|
24
|
-
transaction;
|
|
19
|
+
async (account: Account, transaction: Transaction): Promise<AlgoTransactionPayload> => {
|
|
20
|
+
const { amount, recipient, mode, memo, assetId, subAccountId } = transaction;
|
|
25
21
|
const subAccount = subAccountId
|
|
26
|
-
? account.subAccounts &&
|
|
27
|
-
account.subAccounts.find((t) => t.id === subAccountId)
|
|
22
|
+
? account.subAccounts && account.subAccounts.find(t => t.id === subAccountId)
|
|
28
23
|
: null;
|
|
29
24
|
|
|
30
25
|
const note = memo ? new TextEncoder().encode(memo) : undefined;
|
|
@@ -53,7 +48,7 @@ export const buildTransactionPayload =
|
|
|
53
48
|
note,
|
|
54
49
|
Number(targetAssetId),
|
|
55
50
|
params,
|
|
56
|
-
undefined
|
|
51
|
+
undefined,
|
|
57
52
|
);
|
|
58
53
|
} else {
|
|
59
54
|
algoTxn = makePaymentTxnWithSuggestedParams(
|
|
@@ -62,7 +57,7 @@ export const buildTransactionPayload =
|
|
|
62
57
|
amount.toNumber(),
|
|
63
58
|
undefined,
|
|
64
59
|
note,
|
|
65
|
-
params
|
|
60
|
+
params,
|
|
66
61
|
);
|
|
67
62
|
}
|
|
68
63
|
|
|
@@ -72,7 +67,7 @@ export const buildTransactionPayload =
|
|
|
72
67
|
|
|
73
68
|
// Flaw in the SDK: payload isn't sorted, but it needs to be for msgPack encoding
|
|
74
69
|
const sorted = Object.fromEntries(
|
|
75
|
-
Object.entries(algoTxn.get_obj_for_encoding()).sort()
|
|
70
|
+
Object.entries(algoTxn.get_obj_for_encoding()).sort(),
|
|
76
71
|
) as AlgoTransactionPayload;
|
|
77
72
|
|
|
78
73
|
return sorted;
|
|
@@ -84,10 +79,7 @@ export const encodeToSign = (payload: AlgoTransactionPayload): string => {
|
|
|
84
79
|
return Buffer.from(msgPackEncoded).toString("hex");
|
|
85
80
|
};
|
|
86
81
|
|
|
87
|
-
export const encodeToBroadcast = (
|
|
88
|
-
payload: AlgoTransactionPayload,
|
|
89
|
-
signature: Buffer
|
|
90
|
-
): Buffer => {
|
|
82
|
+
export const encodeToBroadcast = (payload: AlgoTransactionPayload, signature: Buffer): Buffer => {
|
|
91
83
|
const signedPayload: AlgoSignedTransactionPayload = {
|
|
92
84
|
sig: signature,
|
|
93
85
|
txn: payload,
|
package/src/cli-transaction.ts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
import { getAccountCurrency } from "@ledgerhq/coin-framework/account/index";
|
|
2
|
-
import type {
|
|
3
|
-
Account,
|
|
4
|
-
AccountLike,
|
|
5
|
-
AccountLikeArray,
|
|
6
|
-
} from "@ledgerhq/types-live";
|
|
2
|
+
import type { Account, AccountLike, AccountLikeArray } from "@ledgerhq/types-live";
|
|
7
3
|
import invariant from "invariant";
|
|
8
4
|
import flatMap from "lodash/flatMap";
|
|
9
5
|
import { extractTokenId } from "./tokens";
|
|
@@ -39,10 +35,7 @@ const options = [
|
|
|
39
35
|
},
|
|
40
36
|
];
|
|
41
37
|
|
|
42
|
-
function inferAccounts(
|
|
43
|
-
account: Account,
|
|
44
|
-
opts: Record<string, any>
|
|
45
|
-
): AccountLikeArray {
|
|
38
|
+
function inferAccounts(account: Account, opts: Record<string, any>): AccountLikeArray {
|
|
46
39
|
invariant(account.currency.family === "algorand", "algorand family");
|
|
47
40
|
|
|
48
41
|
if (!opts.token || opts.mode === "optIn") {
|
|
@@ -54,7 +47,7 @@ function inferAccounts(
|
|
|
54
47
|
const subAccounts = account.subAccounts || [];
|
|
55
48
|
|
|
56
49
|
if (token) {
|
|
57
|
-
const subAccount = subAccounts.find(
|
|
50
|
+
const subAccount = subAccounts.find(t => {
|
|
58
51
|
const currency = getAccountCurrency(t);
|
|
59
52
|
return (
|
|
60
53
|
token.toLowerCase() === currency.ticker.toLowerCase() ||
|
|
@@ -67,7 +60,7 @@ function inferAccounts(
|
|
|
67
60
|
"token account '" +
|
|
68
61
|
token +
|
|
69
62
|
"' not found. Available: " +
|
|
70
|
-
subAccounts.map(
|
|
63
|
+
subAccounts.map(t => getAccountCurrency(t).ticker).join(", "),
|
|
71
64
|
);
|
|
72
65
|
}
|
|
73
66
|
|
|
@@ -82,16 +75,13 @@ function inferTransactions(
|
|
|
82
75
|
transaction: Transaction;
|
|
83
76
|
}>,
|
|
84
77
|
opts: Record<string, any>,
|
|
85
|
-
{ inferAmount }: any
|
|
78
|
+
{ inferAmount }: any,
|
|
86
79
|
): Transaction[] {
|
|
87
80
|
return flatMap(transactions, ({ transaction, account }) => {
|
|
88
81
|
invariant(transaction.family === "algorand", "algorand family");
|
|
89
82
|
|
|
90
83
|
if (account.type === "Account") {
|
|
91
|
-
invariant(
|
|
92
|
-
(account as AlgorandAccount).algorandResources,
|
|
93
|
-
"unactivated account"
|
|
94
|
-
);
|
|
84
|
+
invariant((account as AlgorandAccount).algorandResources, "unactivated account");
|
|
95
85
|
}
|
|
96
86
|
|
|
97
87
|
if (account.type === "TokenAccount") {
|