@ledgerhq/live-common 34.39.0 → 34.40.0-nightly.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/lib/__tests__/test-helpers/bridge.d.ts.map +1 -1
- package/lib/__tests__/test-helpers/bridge.js +5 -1
- package/lib/__tests__/test-helpers/bridge.js.map +1 -1
- package/lib/apps/support.d.ts +2 -1
- package/lib/apps/support.d.ts.map +1 -1
- package/lib/apps/support.js +3 -2
- package/lib/apps/support.js.map +1 -1
- package/lib/apps/support.test.js +35 -0
- package/lib/apps/support.test.js.map +1 -1
- package/lib/bridge/generic-alpaca/accountBridge.d.ts +3 -0
- package/lib/bridge/generic-alpaca/accountBridge.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/accountBridge.js +34 -0
- package/lib/bridge/generic-alpaca/accountBridge.js.map +1 -0
- package/lib/bridge/generic-alpaca/alpaca/index.d.ts +3 -0
- package/lib/bridge/generic-alpaca/alpaca/index.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/alpaca/index.js +20 -0
- package/lib/bridge/generic-alpaca/alpaca/index.js.map +1 -0
- package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts +17 -0
- package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.js +131 -0
- package/lib/bridge/generic-alpaca/alpaca/network/network-alpaca.js.map +1 -0
- package/lib/bridge/generic-alpaca/broadcast.d.ts +3 -0
- package/lib/bridge/generic-alpaca/broadcast.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/broadcast.js +11 -0
- package/lib/bridge/generic-alpaca/broadcast.js.map +1 -0
- package/lib/bridge/generic-alpaca/createTransaction.d.ts +16 -0
- package/lib/bridge/generic-alpaca/createTransaction.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/createTransaction.js +20 -0
- package/lib/bridge/generic-alpaca/createTransaction.js.map +1 -0
- package/lib/bridge/generic-alpaca/currencyBridge.d.ts +3 -0
- package/lib/bridge/generic-alpaca/currencyBridge.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/currencyBridge.js +20 -0
- package/lib/bridge/generic-alpaca/currencyBridge.js.map +1 -0
- package/lib/bridge/generic-alpaca/estimateMaxSpendable.d.ts +3 -0
- package/lib/bridge/generic-alpaca/estimateMaxSpendable.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/estimateMaxSpendable.js +26 -0
- package/lib/bridge/generic-alpaca/estimateMaxSpendable.js.map +1 -0
- package/lib/bridge/generic-alpaca/getAccountShape.d.ts +3 -0
- package/lib/bridge/generic-alpaca/getAccountShape.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/getAccountShape.js +58 -0
- package/lib/bridge/generic-alpaca/getAccountShape.js.map +1 -0
- package/lib/bridge/generic-alpaca/getTransactionStatus.d.ts +3 -0
- package/lib/bridge/generic-alpaca/getTransactionStatus.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/getTransactionStatus.js +36 -0
- package/lib/bridge/generic-alpaca/getTransactionStatus.js.map +1 -0
- package/lib/bridge/generic-alpaca/prepareTransaction.d.ts +3 -0
- package/lib/bridge/generic-alpaca/prepareTransaction.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/prepareTransaction.js +24 -0
- package/lib/bridge/generic-alpaca/prepareTransaction.js.map +1 -0
- package/lib/bridge/generic-alpaca/signOperation.d.ts +7 -0
- package/lib/bridge/generic-alpaca/signOperation.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/signOperation.js +61 -0
- package/lib/bridge/generic-alpaca/signOperation.js.map +1 -0
- package/lib/bridge/generic-alpaca/signer/index.d.ts +11 -0
- package/lib/bridge/generic-alpaca/signer/index.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/signer/index.js +28 -0
- package/lib/bridge/generic-alpaca/signer/index.js.map +1 -0
- package/lib/bridge/generic-alpaca/signer/signTransaction.d.ts +5 -0
- package/lib/bridge/generic-alpaca/signer/signTransaction.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/signer/signTransaction.js +11 -0
- package/lib/bridge/generic-alpaca/signer/signTransaction.js.map +1 -0
- package/lib/bridge/generic-alpaca/signer/types.d.ts +5 -0
- package/lib/bridge/generic-alpaca/signer/types.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/signer/types.js +3 -0
- package/lib/bridge/generic-alpaca/signer/types.js.map +1 -0
- package/lib/bridge/generic-alpaca/tests/estimateMaxSpendable.test.d.ts +2 -0
- package/lib/bridge/generic-alpaca/tests/estimateMaxSpendable.test.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/tests/estimateMaxSpendable.test.js +90 -0
- package/lib/bridge/generic-alpaca/tests/estimateMaxSpendable.test.js.map +1 -0
- package/lib/bridge/generic-alpaca/tests/prepareTransaction.test.d.ts +2 -0
- package/lib/bridge/generic-alpaca/tests/prepareTransaction.test.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/tests/prepareTransaction.test.js +73 -0
- package/lib/bridge/generic-alpaca/tests/prepareTransaction.test.js.map +1 -0
- package/lib/bridge/generic-alpaca/tests/signOperation.test.d.ts +2 -0
- package/lib/bridge/generic-alpaca/tests/signOperation.test.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/tests/signOperation.test.js +80 -0
- package/lib/bridge/generic-alpaca/tests/signOperation.test.js.map +1 -0
- package/lib/bridge/generic-alpaca/utils.d.ts +6 -0
- package/lib/bridge/generic-alpaca/utils.d.ts.map +1 -0
- package/lib/bridge/generic-alpaca/utils.js +56 -0
- package/lib/bridge/generic-alpaca/utils.js.map +1 -0
- package/lib/bridge/impl.d.ts.map +1 -1
- package/lib/bridge/impl.js +21 -1
- package/lib/bridge/impl.js.map +1 -1
- package/lib/exchange/providers/swap.d.ts.map +1 -1
- package/lib/exchange/providers/swap.integration.test.js +9 -0
- package/lib/exchange/providers/swap.integration.test.js.map +1 -1
- package/lib/exchange/providers/swap.js +8 -0
- package/lib/exchange/providers/swap.js.map +1 -1
- package/lib/families/evm/config.js +2 -2
- package/lib/families/evm/config.js.map +1 -1
- package/lib/families/solana/bridge/mock-data.d.ts.map +1 -1
- package/lib/families/solana/bridge/mock-data.js +399 -1
- package/lib/families/solana/bridge/mock-data.js.map +1 -1
- package/lib/families/solana/bridge/mock.d.ts +58 -0
- package/lib/families/solana/bridge/mock.d.ts.map +1 -1
- package/lib/families/solana/bridge/mock.js +58 -14
- package/lib/families/solana/bridge/mock.js.map +1 -1
- package/lib/families/xrp/setup.d.ts +3 -6
- package/lib/families/xrp/setup.d.ts.map +1 -1
- package/lib/families/xrp/setup.js +1 -7
- package/lib/families/xrp/setup.js.map +1 -1
- package/lib/generated/bridge/js.d.ts +0 -1
- package/lib/generated/bridge/js.d.ts.map +1 -1
- package/lib/generated/bridge/js.js +4 -6
- package/lib/generated/bridge/js.js.map +1 -1
- package/lib/generated/bridge/mock.d.ts +58 -0
- package/lib/generated/bridge/mock.d.ts.map +1 -1
- package/lib/hw/connectApp.d.ts.map +1 -1
- package/lib/hw/connectApp.js +11 -5
- package/lib/hw/connectApp.js.map +1 -1
- package/lib/wallet-api/react.d.ts.map +1 -1
- package/lib/wallet-api/react.js +3 -1
- package/lib/wallet-api/react.js.map +1 -1
- package/lib-es/__tests__/test-helpers/bridge.d.ts.map +1 -1
- package/lib-es/__tests__/test-helpers/bridge.js +5 -1
- package/lib-es/__tests__/test-helpers/bridge.js.map +1 -1
- package/lib-es/apps/support.d.ts +2 -1
- package/lib-es/apps/support.d.ts.map +1 -1
- package/lib-es/apps/support.js +3 -2
- package/lib-es/apps/support.js.map +1 -1
- package/lib-es/apps/support.test.js +36 -1
- package/lib-es/apps/support.test.js.map +1 -1
- package/lib-es/bridge/generic-alpaca/accountBridge.d.ts +3 -0
- package/lib-es/bridge/generic-alpaca/accountBridge.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/accountBridge.js +27 -0
- package/lib-es/bridge/generic-alpaca/accountBridge.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/alpaca/index.d.ts +3 -0
- package/lib-es/bridge/generic-alpaca/alpaca/index.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/alpaca/index.js +16 -0
- package/lib-es/bridge/generic-alpaca/alpaca/index.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts +17 -0
- package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.js +124 -0
- package/lib-es/bridge/generic-alpaca/alpaca/network/network-alpaca.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/broadcast.d.ts +3 -0
- package/lib-es/bridge/generic-alpaca/broadcast.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/broadcast.js +7 -0
- package/lib-es/bridge/generic-alpaca/broadcast.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/createTransaction.d.ts +16 -0
- package/lib-es/bridge/generic-alpaca/createTransaction.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/createTransaction.js +13 -0
- package/lib-es/bridge/generic-alpaca/createTransaction.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/currencyBridge.d.ts +3 -0
- package/lib-es/bridge/generic-alpaca/currencyBridge.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/currencyBridge.js +16 -0
- package/lib-es/bridge/generic-alpaca/currencyBridge.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/estimateMaxSpendable.d.ts +3 -0
- package/lib-es/bridge/generic-alpaca/estimateMaxSpendable.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/estimateMaxSpendable.js +19 -0
- package/lib-es/bridge/generic-alpaca/estimateMaxSpendable.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/getAccountShape.d.ts +3 -0
- package/lib-es/bridge/generic-alpaca/getAccountShape.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/getAccountShape.js +51 -0
- package/lib-es/bridge/generic-alpaca/getAccountShape.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/getTransactionStatus.d.ts +3 -0
- package/lib-es/bridge/generic-alpaca/getTransactionStatus.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/getTransactionStatus.js +29 -0
- package/lib-es/bridge/generic-alpaca/getTransactionStatus.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/prepareTransaction.d.ts +3 -0
- package/lib-es/bridge/generic-alpaca/prepareTransaction.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/prepareTransaction.js +17 -0
- package/lib-es/bridge/generic-alpaca/prepareTransaction.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/signOperation.d.ts +7 -0
- package/lib-es/bridge/generic-alpaca/signOperation.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/signOperation.js +57 -0
- package/lib-es/bridge/generic-alpaca/signOperation.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/signer/index.d.ts +11 -0
- package/lib-es/bridge/generic-alpaca/signer/index.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/signer/index.js +21 -0
- package/lib-es/bridge/generic-alpaca/signer/index.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/signer/signTransaction.d.ts +5 -0
- package/lib-es/bridge/generic-alpaca/signer/signTransaction.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/signer/signTransaction.js +7 -0
- package/lib-es/bridge/generic-alpaca/signer/signTransaction.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/signer/types.d.ts +5 -0
- package/lib-es/bridge/generic-alpaca/signer/types.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/signer/types.js +2 -0
- package/lib-es/bridge/generic-alpaca/signer/types.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/tests/estimateMaxSpendable.test.d.ts +2 -0
- package/lib-es/bridge/generic-alpaca/tests/estimateMaxSpendable.test.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/tests/estimateMaxSpendable.test.js +62 -0
- package/lib-es/bridge/generic-alpaca/tests/estimateMaxSpendable.test.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/tests/prepareTransaction.test.d.ts +2 -0
- package/lib-es/bridge/generic-alpaca/tests/prepareTransaction.test.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/tests/prepareTransaction.test.js +68 -0
- package/lib-es/bridge/generic-alpaca/tests/prepareTransaction.test.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/tests/signOperation.test.d.ts +2 -0
- package/lib-es/bridge/generic-alpaca/tests/signOperation.test.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/tests/signOperation.test.js +78 -0
- package/lib-es/bridge/generic-alpaca/tests/signOperation.test.js.map +1 -0
- package/lib-es/bridge/generic-alpaca/utils.d.ts +6 -0
- package/lib-es/bridge/generic-alpaca/utils.d.ts.map +1 -0
- package/lib-es/bridge/generic-alpaca/utils.js +47 -0
- package/lib-es/bridge/generic-alpaca/utils.js.map +1 -0
- package/lib-es/bridge/impl.d.ts.map +1 -1
- package/lib-es/bridge/impl.js +21 -1
- package/lib-es/bridge/impl.js.map +1 -1
- package/lib-es/exchange/providers/swap.d.ts.map +1 -1
- package/lib-es/exchange/providers/swap.integration.test.js +9 -0
- package/lib-es/exchange/providers/swap.integration.test.js.map +1 -1
- package/lib-es/exchange/providers/swap.js +8 -0
- package/lib-es/exchange/providers/swap.js.map +1 -1
- package/lib-es/families/evm/config.js +2 -2
- package/lib-es/families/evm/config.js.map +1 -1
- package/lib-es/families/solana/bridge/mock-data.d.ts.map +1 -1
- package/lib-es/families/solana/bridge/mock-data.js +400 -2
- package/lib-es/families/solana/bridge/mock-data.js.map +1 -1
- package/lib-es/families/solana/bridge/mock.d.ts +58 -0
- package/lib-es/families/solana/bridge/mock.d.ts.map +1 -1
- package/lib-es/families/solana/bridge/mock.js +58 -14
- package/lib-es/families/solana/bridge/mock.js.map +1 -1
- package/lib-es/families/xrp/setup.d.ts +3 -6
- package/lib-es/families/xrp/setup.d.ts.map +1 -1
- package/lib-es/families/xrp/setup.js +2 -7
- package/lib-es/families/xrp/setup.js.map +1 -1
- package/lib-es/generated/bridge/js.d.ts +0 -1
- package/lib-es/generated/bridge/js.d.ts.map +1 -1
- package/lib-es/generated/bridge/js.js +0 -2
- package/lib-es/generated/bridge/js.js.map +1 -1
- package/lib-es/generated/bridge/mock.d.ts +58 -0
- package/lib-es/generated/bridge/mock.d.ts.map +1 -1
- package/lib-es/hw/connectApp.d.ts.map +1 -1
- package/lib-es/hw/connectApp.js +11 -5
- package/lib-es/hw/connectApp.js.map +1 -1
- package/lib-es/wallet-api/react.d.ts.map +1 -1
- package/lib-es/wallet-api/react.js +3 -1
- package/lib-es/wallet-api/react.js.map +1 -1
- package/package.json +37 -37
- package/src/__tests__/test-helpers/bridge.ts +3 -2
- package/src/apps/support.test.ts +42 -1
- package/src/apps/support.ts +5 -3
- package/src/bridge/generic-alpaca/accountBridge.ts +35 -0
- package/src/bridge/generic-alpaca/alpaca/index.ts +20 -0
- package/src/bridge/generic-alpaca/alpaca/network/network-alpaca.ts +193 -0
- package/src/bridge/generic-alpaca/broadcast.ts +14 -0
- package/src/bridge/generic-alpaca/createTransaction.ts +27 -0
- package/src/bridge/generic-alpaca/currencyBridge.ts +17 -0
- package/src/bridge/generic-alpaca/estimateMaxSpendable.ts +27 -0
- package/src/bridge/generic-alpaca/getAccountShape.ts +62 -0
- package/src/bridge/generic-alpaca/getTransactionStatus.ts +38 -0
- package/src/bridge/generic-alpaca/prepareTransaction.ts +26 -0
- package/src/bridge/generic-alpaca/signOperation.ts +98 -0
- package/src/bridge/generic-alpaca/signer/index.ts +33 -0
- package/src/bridge/generic-alpaca/signer/signTransaction.ts +13 -0
- package/src/bridge/generic-alpaca/signer/types.ts +4 -0
- package/src/bridge/generic-alpaca/tests/estimateMaxSpendable.test.ts +76 -0
- package/src/bridge/generic-alpaca/tests/prepareTransaction.test.ts +92 -0
- package/src/bridge/generic-alpaca/tests/signOperation.test.ts +97 -0
- package/src/bridge/generic-alpaca/utils.ts +65 -0
- package/src/bridge/impl.ts +25 -1
- package/src/exchange/providers/swap.integration.test.ts +9 -0
- package/src/exchange/providers/swap.ts +8 -0
- package/src/families/evm/config.ts +2 -2
- package/src/families/solana/bridge/mock-data.ts +404 -2
- package/src/families/solana/bridge/mock.ts +73 -21
- package/src/families/xrp/setup.ts +2 -15
- package/src/generated/bridge/js.ts +0 -2
- package/src/hw/connectApp.ts +14 -5
- package/src/wallet-api/react.ts +3 -1
@@ -0,0 +1,26 @@
|
|
1
|
+
import { Account, AccountBridge, TransactionCommon } from "@ledgerhq/types-live";
|
2
|
+
import { getAlpacaApi } from "./alpaca";
|
3
|
+
import { transactionToIntent } from "./utils";
|
4
|
+
import BigNumber from "bignumber.js";
|
5
|
+
|
6
|
+
function bnEq(a: BigNumber | null | undefined, b: BigNumber | null | undefined): boolean {
|
7
|
+
return !a && !b ? true : !a || !b ? false : a.eq(b);
|
8
|
+
}
|
9
|
+
|
10
|
+
export function genericPrepareTransaction(
|
11
|
+
network: string,
|
12
|
+
kind: "local" | "remote",
|
13
|
+
): AccountBridge<TransactionCommon, Account, any, any>["prepareTransaction"] {
|
14
|
+
return async (account, transaction: TransactionCommon & { fees: BigNumber }) => {
|
15
|
+
const fees = await getAlpacaApi(network, kind).estimateFees(
|
16
|
+
transactionToIntent(account, transaction),
|
17
|
+
);
|
18
|
+
const bnFee = BigNumber(fees.value.toString());
|
19
|
+
|
20
|
+
if (!bnEq(transaction.fees, bnFee)) {
|
21
|
+
return { ...transaction, fees: bnFee };
|
22
|
+
}
|
23
|
+
|
24
|
+
return transaction;
|
25
|
+
};
|
26
|
+
}
|
@@ -0,0 +1,98 @@
|
|
1
|
+
import { Observable } from "rxjs";
|
2
|
+
import { SignerContext } from "@ledgerhq/coin-framework/signer";
|
3
|
+
import type {
|
4
|
+
Account,
|
5
|
+
DeviceId,
|
6
|
+
SignOperationEvent,
|
7
|
+
AccountBridge,
|
8
|
+
TransactionCommon,
|
9
|
+
} from "@ledgerhq/types-live";
|
10
|
+
import { getAlpacaApi } from "./alpaca";
|
11
|
+
import { buildOptimisticOperation, transactionToIntent } from "./utils";
|
12
|
+
import { FeeNotLoaded } from "@ledgerhq/errors";
|
13
|
+
import { Result } from "@ledgerhq/coin-framework/derivation";
|
14
|
+
import { MapMemo, TransactionIntent } from "@ledgerhq/coin-framework/api/types";
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Sign Transaction with Ledger hardware
|
18
|
+
*/
|
19
|
+
export const genericSignOperation =
|
20
|
+
(network: string, kind: "local" | "remote") =>
|
21
|
+
(signerContext: SignerContext<any>): AccountBridge<TransactionCommon>["signOperation"] =>
|
22
|
+
({
|
23
|
+
account,
|
24
|
+
transaction,
|
25
|
+
deviceId,
|
26
|
+
}: {
|
27
|
+
account: Account;
|
28
|
+
transaction: TransactionCommon;
|
29
|
+
deviceId: DeviceId;
|
30
|
+
}): Observable<SignOperationEvent> =>
|
31
|
+
new Observable(o => {
|
32
|
+
async function main() {
|
33
|
+
if (!transaction["fees"]) throw new FeeNotLoaded();
|
34
|
+
|
35
|
+
const signedInfo = await signerContext(deviceId, async signer => {
|
36
|
+
const derivationPath = account.freshAddressPath;
|
37
|
+
|
38
|
+
const { publicKey } = (await signer.getAddress(derivationPath)) as Result;
|
39
|
+
|
40
|
+
const transactionIntent = transactionToIntent(account, transaction);
|
41
|
+
transactionIntent.senderPublicKey = publicKey;
|
42
|
+
// NOTE: is setting the memo here instead of transactionToIntent sensible?
|
43
|
+
const txWithMemo = transactionIntent as TransactionIntent<any, MapMemo<string, string>>;
|
44
|
+
if (transaction["tag"]) {
|
45
|
+
const txMemo = String(transaction["tag"]);
|
46
|
+
txWithMemo.memo = {
|
47
|
+
type: "map",
|
48
|
+
memos: new Map(),
|
49
|
+
};
|
50
|
+
txWithMemo.memo.memos.set("destinationTag", txMemo);
|
51
|
+
}
|
52
|
+
|
53
|
+
/* Craft unsigned blob via Alpaca */
|
54
|
+
const unsigned: string = await getAlpacaApi(network, kind).craftTransaction(
|
55
|
+
transactionIntent,
|
56
|
+
);
|
57
|
+
|
58
|
+
// TODO: should compute it and pass it down to craftTransaction (duplicate call right now)
|
59
|
+
const accountInfo = await getAlpacaApi(network, kind).getAccountInfo(
|
60
|
+
transactionIntent.sender,
|
61
|
+
);
|
62
|
+
const sequenceNumber = accountInfo.sequence;
|
63
|
+
|
64
|
+
/* Notify UI that the device is now showing the tx */
|
65
|
+
o.next({ type: "device-signature-requested" });
|
66
|
+
/* Sign on Ledger device */
|
67
|
+
const txnSig = await signer.signTransaction(derivationPath, unsigned);
|
68
|
+
return { unsigned, txnSig, publicKey, sequence: sequenceNumber };
|
69
|
+
});
|
70
|
+
|
71
|
+
/* If the user cancelled inside signerContext */
|
72
|
+
if (!signedInfo) return;
|
73
|
+
o.next({ type: "device-signature-granted" });
|
74
|
+
|
75
|
+
/* Combine payload + signature for broadcast */
|
76
|
+
const combined = await getAlpacaApi(network, kind).combine(
|
77
|
+
signedInfo.unsigned,
|
78
|
+
signedInfo.txnSig,
|
79
|
+
signedInfo.publicKey,
|
80
|
+
);
|
81
|
+
|
82
|
+
const operation = buildOptimisticOperation(account, transaction, signedInfo.sequence);
|
83
|
+
// NOTE: we set the transactionSequenceNumber before on the operation
|
84
|
+
// now that we create it in craftTransaction, we might need to return it back from craftTransaction also
|
85
|
+
o.next({
|
86
|
+
type: "signed",
|
87
|
+
signedOperation: {
|
88
|
+
operation,
|
89
|
+
signature: combined,
|
90
|
+
},
|
91
|
+
});
|
92
|
+
}
|
93
|
+
|
94
|
+
main().then(
|
95
|
+
() => o.complete(),
|
96
|
+
e => o.error(e),
|
97
|
+
);
|
98
|
+
});
|
@@ -0,0 +1,33 @@
|
|
1
|
+
import { GetAddressFn } from "@ledgerhq/coin-framework/bridge/getAddressWrapper";
|
2
|
+
import xrpGetAddress from "@ledgerhq/coin-xrp/signer/getAddress";
|
3
|
+
import { CreateSigner, executeWithSigner } from "../../setup";
|
4
|
+
import Xrp from "@ledgerhq/hw-app-xrp";
|
5
|
+
|
6
|
+
import Transport from "@ledgerhq/hw-transport";
|
7
|
+
import { signTransaction } from "./signTransaction";
|
8
|
+
import { SignerContext } from "@ledgerhq/coin-framework/signer";
|
9
|
+
import { SignTransactionOptions } from "./types";
|
10
|
+
|
11
|
+
export type AlpacaSigner = {
|
12
|
+
getAddress: GetAddressFn;
|
13
|
+
signTransaction?: (deviceId: string, opts: SignTransactionOptions) => Promise<string>;
|
14
|
+
signMessage?: (message: string) => Promise<string>;
|
15
|
+
context: SignerContext<any>;
|
16
|
+
};
|
17
|
+
|
18
|
+
export function getSigner(network: string): AlpacaSigner {
|
19
|
+
switch (network) {
|
20
|
+
case "ripple":
|
21
|
+
case "xrp": {
|
22
|
+
const createSigner: CreateSigner<Xrp> = (transport: Transport) => {
|
23
|
+
return new Xrp(transport);
|
24
|
+
};
|
25
|
+
return {
|
26
|
+
getAddress: xrpGetAddress(executeWithSigner(createSigner)),
|
27
|
+
signTransaction: signTransaction(executeWithSigner(createSigner)),
|
28
|
+
context: executeWithSigner(createSigner),
|
29
|
+
};
|
30
|
+
}
|
31
|
+
}
|
32
|
+
throw new Error(`signer for ${network} not implemented`);
|
33
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
import { SignerContext } from "@ledgerhq/coin-framework/signer";
|
2
|
+
import { XrpSigner } from "@ledgerhq/coin-xrp/index";
|
3
|
+
import { SignTransactionOptions } from "./types";
|
4
|
+
|
5
|
+
export const signTransaction = (signerContext: SignerContext<XrpSigner>) => {
|
6
|
+
return async (deviceId: string, { path, rawTxHex }: SignTransactionOptions) => {
|
7
|
+
const signedTx = await signerContext(deviceId, signer =>
|
8
|
+
signer.signTransaction(path, rawTxHex),
|
9
|
+
);
|
10
|
+
|
11
|
+
return signedTx;
|
12
|
+
};
|
13
|
+
};
|
@@ -0,0 +1,76 @@
|
|
1
|
+
import BigNumber from "bignumber.js";
|
2
|
+
import { genericEstimateMaxSpendable } from "../estimateMaxSpendable";
|
3
|
+
import * as alpaca from "../alpaca";
|
4
|
+
import { Account } from "@ledgerhq/types-live";
|
5
|
+
|
6
|
+
// Mock the alpaca API
|
7
|
+
jest.mock("../alpaca", () => ({
|
8
|
+
getAlpacaApi: jest.fn(),
|
9
|
+
}));
|
10
|
+
|
11
|
+
const mockedGetAlpacaApi = alpaca.getAlpacaApi as jest.Mock;
|
12
|
+
|
13
|
+
// Dummy data
|
14
|
+
const dummyAccount = {
|
15
|
+
id: "js:2:ripple:r123:",
|
16
|
+
type: "Account", // <-- this is mandatory for getMainAccount to work
|
17
|
+
spendableBalance: new BigNumber(50000000),
|
18
|
+
currency: { id: "ripple", name: "XRP", units: [{ name: "XRP", magnitude: 6 }] },
|
19
|
+
freshAddress: "r123",
|
20
|
+
} as unknown as Account;
|
21
|
+
|
22
|
+
describe("genericEstimateMaxSpendable", () => {
|
23
|
+
afterEach(() => {
|
24
|
+
jest.clearAllMocks();
|
25
|
+
});
|
26
|
+
|
27
|
+
it("subtracts estimated fee from spendable balance", async () => {
|
28
|
+
mockedGetAlpacaApi.mockReturnValue({
|
29
|
+
estimateFees: jest.fn().mockResolvedValue({ value: 10000n }), // 0.01 XRP
|
30
|
+
});
|
31
|
+
|
32
|
+
const estimate = genericEstimateMaxSpendable("xrp", "local");
|
33
|
+
const result = await estimate({
|
34
|
+
account: dummyAccount,
|
35
|
+
parentAccount: null,
|
36
|
+
transaction: {},
|
37
|
+
});
|
38
|
+
|
39
|
+
expect(result.toString()).toBe("49990000"); // 50_000_000 - 10_000
|
40
|
+
});
|
41
|
+
|
42
|
+
it("returns 0 if fee is higher than spendable", async () => {
|
43
|
+
const poorAccount = {
|
44
|
+
...dummyAccount,
|
45
|
+
spendableBalance: new BigNumber(5000), // very low
|
46
|
+
};
|
47
|
+
|
48
|
+
mockedGetAlpacaApi.mockReturnValue({
|
49
|
+
estimateFees: jest.fn().mockResolvedValue({ value: 10000n }),
|
50
|
+
});
|
51
|
+
|
52
|
+
const estimate = genericEstimateMaxSpendable("xrp", "local");
|
53
|
+
const result = await estimate({
|
54
|
+
account: poorAccount,
|
55
|
+
parentAccount: null,
|
56
|
+
transaction: {},
|
57
|
+
});
|
58
|
+
|
59
|
+
expect(result.toString()).toBe("0");
|
60
|
+
});
|
61
|
+
|
62
|
+
it("returns full spendable balance if fee is 0", async () => {
|
63
|
+
mockedGetAlpacaApi.mockReturnValue({
|
64
|
+
estimateFees: jest.fn().mockResolvedValue({ value: 0n }),
|
65
|
+
});
|
66
|
+
|
67
|
+
const estimate = genericEstimateMaxSpendable("xrp", "local");
|
68
|
+
const result = await estimate({
|
69
|
+
account: dummyAccount,
|
70
|
+
parentAccount: null,
|
71
|
+
transaction: {},
|
72
|
+
});
|
73
|
+
|
74
|
+
expect(result.toString()).toBe("50000000");
|
75
|
+
});
|
76
|
+
});
|
@@ -0,0 +1,92 @@
|
|
1
|
+
import { genericPrepareTransaction } from "../prepareTransaction";
|
2
|
+
import { getAlpacaApi } from "../alpaca";
|
3
|
+
import { transactionToIntent } from "../utils";
|
4
|
+
import BigNumber from "bignumber.js";
|
5
|
+
import type { TransactionCommon } from "@ledgerhq/types-live";
|
6
|
+
|
7
|
+
jest.mock("../alpaca", () => ({
|
8
|
+
getAlpacaApi: jest.fn(),
|
9
|
+
}));
|
10
|
+
|
11
|
+
jest.mock("../utils", () => ({
|
12
|
+
transactionToIntent: jest.fn(),
|
13
|
+
}));
|
14
|
+
|
15
|
+
describe("genericPrepareTransaction", () => {
|
16
|
+
const network = "testnet";
|
17
|
+
const kind = "local";
|
18
|
+
|
19
|
+
const account = {
|
20
|
+
id: "test-account",
|
21
|
+
address: "0xabc",
|
22
|
+
} as any;
|
23
|
+
|
24
|
+
const baseTransaction: TransactionCommon & { fees: BigNumber } = {
|
25
|
+
amount: new BigNumber(100_000),
|
26
|
+
fees: new BigNumber(500),
|
27
|
+
recipient: "0xrecipient",
|
28
|
+
};
|
29
|
+
|
30
|
+
const txIntent = { mock: "intent" };
|
31
|
+
|
32
|
+
beforeEach(() => {
|
33
|
+
jest.clearAllMocks();
|
34
|
+
(transactionToIntent as jest.Mock).mockReturnValue(txIntent);
|
35
|
+
});
|
36
|
+
|
37
|
+
it("updates fees if they differ", async () => {
|
38
|
+
const newFee = new BigNumber(700);
|
39
|
+
|
40
|
+
(getAlpacaApi as jest.Mock).mockReturnValue({
|
41
|
+
estimateFees: jest.fn().mockResolvedValue({ value: newFee }),
|
42
|
+
});
|
43
|
+
|
44
|
+
const prepareTransaction = genericPrepareTransaction(network, kind);
|
45
|
+
const result = await prepareTransaction(account, { ...baseTransaction });
|
46
|
+
|
47
|
+
expect((result as any).fees.toString()).toBe(newFee.toString());
|
48
|
+
expect(transactionToIntent).toHaveBeenCalledWith(
|
49
|
+
account,
|
50
|
+
expect.objectContaining(baseTransaction),
|
51
|
+
);
|
52
|
+
});
|
53
|
+
|
54
|
+
it("returns original transaction if fees are the same", async () => {
|
55
|
+
const sameFee = baseTransaction.fees;
|
56
|
+
|
57
|
+
(getAlpacaApi as jest.Mock).mockReturnValue({
|
58
|
+
estimateFees: jest.fn().mockResolvedValue({ value: sameFee }),
|
59
|
+
});
|
60
|
+
|
61
|
+
const prepareTransaction = genericPrepareTransaction(network, kind);
|
62
|
+
const result = await prepareTransaction(account, baseTransaction);
|
63
|
+
|
64
|
+
expect(result).toBe(baseTransaction);
|
65
|
+
});
|
66
|
+
|
67
|
+
it("sets fee if original fees are undefined", async () => {
|
68
|
+
const newFee = new BigNumber(1234);
|
69
|
+
(getAlpacaApi as jest.Mock).mockReturnValue({
|
70
|
+
estimateFees: jest.fn().mockResolvedValue({ value: newFee }),
|
71
|
+
});
|
72
|
+
|
73
|
+
const txWithoutFees = { ...baseTransaction, fees: undefined as any };
|
74
|
+
const prepareTransaction = genericPrepareTransaction(network, kind);
|
75
|
+
const result = await prepareTransaction(account, txWithoutFees);
|
76
|
+
|
77
|
+
expect((result as any).fees.toString()).toBe(newFee.toString());
|
78
|
+
expect(result).not.toBe(txWithoutFees);
|
79
|
+
});
|
80
|
+
|
81
|
+
it("returns original if fees are BigNumber-equal but different instance", async () => {
|
82
|
+
const sameValue = new BigNumber(baseTransaction.fees.toString()); // different instance
|
83
|
+
(getAlpacaApi as jest.Mock).mockReturnValue({
|
84
|
+
estimateFees: jest.fn().mockResolvedValue({ value: sameValue }),
|
85
|
+
});
|
86
|
+
|
87
|
+
const prepareTransaction = genericPrepareTransaction(network, kind);
|
88
|
+
const result = await prepareTransaction(account, baseTransaction);
|
89
|
+
|
90
|
+
expect(result).toBe(baseTransaction); // still same reference
|
91
|
+
});
|
92
|
+
});
|
@@ -0,0 +1,97 @@
|
|
1
|
+
import { lastValueFrom } from "rxjs";
|
2
|
+
import { toArray } from "rxjs/operators";
|
3
|
+
import { genericSignOperation } from "../signOperation";
|
4
|
+
import { FeeNotLoaded } from "@ledgerhq/errors";
|
5
|
+
import { getAlpacaApi } from "../alpaca";
|
6
|
+
import { buildOptimisticOperation, transactionToIntent } from "../utils";
|
7
|
+
|
8
|
+
jest.mock("../alpaca", () => ({
|
9
|
+
getAlpacaApi: jest.fn(),
|
10
|
+
}));
|
11
|
+
|
12
|
+
jest.mock("../utils", () => ({
|
13
|
+
buildOptimisticOperation: jest.fn(),
|
14
|
+
transactionToIntent: jest.fn(),
|
15
|
+
}));
|
16
|
+
|
17
|
+
describe("genericSignOperation", () => {
|
18
|
+
const network = "xrp";
|
19
|
+
const kind = "local";
|
20
|
+
|
21
|
+
const mockSignerContext = jest.fn();
|
22
|
+
const mockSigner = {
|
23
|
+
getAddress: jest.fn(),
|
24
|
+
signTransaction: jest.fn(),
|
25
|
+
};
|
26
|
+
|
27
|
+
const account = {
|
28
|
+
freshAddressPath: "44'/144'/0'/0/0",
|
29
|
+
address: "rTestAddress",
|
30
|
+
} as any;
|
31
|
+
|
32
|
+
const transaction = {
|
33
|
+
amount: 100_000n,
|
34
|
+
fees: 500n,
|
35
|
+
tag: 1234,
|
36
|
+
} as any;
|
37
|
+
|
38
|
+
const deviceId = "mockDevice";
|
39
|
+
|
40
|
+
const txIntent = {
|
41
|
+
memo: {
|
42
|
+
type: "map",
|
43
|
+
memos: new Map(),
|
44
|
+
},
|
45
|
+
};
|
46
|
+
|
47
|
+
const unsignedTx = "unsignedTx";
|
48
|
+
const signedTx = "signedTx";
|
49
|
+
const pubKey = "pubKey";
|
50
|
+
|
51
|
+
beforeEach(() => {
|
52
|
+
jest.clearAllMocks();
|
53
|
+
|
54
|
+
(getAlpacaApi as jest.Mock).mockReturnValue({
|
55
|
+
craftTransaction: jest.fn().mockResolvedValue(unsignedTx),
|
56
|
+
getAccountInfo: jest.fn().mockResolvedValue(pubKey),
|
57
|
+
combine: jest.fn().mockResolvedValue(signedTx),
|
58
|
+
});
|
59
|
+
|
60
|
+
(transactionToIntent as jest.Mock).mockReturnValue(txIntent);
|
61
|
+
(buildOptimisticOperation as jest.Mock).mockReturnValue({ id: "mock-op" });
|
62
|
+
|
63
|
+
mockSigner.getAddress.mockResolvedValue({ publicKey: pubKey });
|
64
|
+
mockSigner.signTransaction.mockResolvedValue("sig");
|
65
|
+
mockSignerContext.mockImplementation(async (_deviceId, cb) => cb(mockSigner));
|
66
|
+
});
|
67
|
+
|
68
|
+
it("emits full sign operation flow", async () => {
|
69
|
+
const signOperation = genericSignOperation(network, kind)(mockSignerContext);
|
70
|
+
const observable = signOperation({ account, transaction, deviceId });
|
71
|
+
|
72
|
+
const events = await lastValueFrom(observable.pipe(toArray()));
|
73
|
+
|
74
|
+
expect(events[0]).toEqual({ type: "device-signature-requested" });
|
75
|
+
expect(events[1]).toEqual({ type: "device-signature-granted" });
|
76
|
+
expect(events[2]).toEqual({
|
77
|
+
type: "signed",
|
78
|
+
signedOperation: {
|
79
|
+
operation: { id: "mock-op" },
|
80
|
+
signature: signedTx,
|
81
|
+
},
|
82
|
+
});
|
83
|
+
|
84
|
+
expect(transactionToIntent).toHaveBeenCalledWith(account, transaction);
|
85
|
+
expect(txIntent.memo.memos.get("destinationTag")).toBe("1234");
|
86
|
+
});
|
87
|
+
|
88
|
+
it("throws FeeNotLoaded if fees are missing", async () => {
|
89
|
+
const txWithoutFees = { ...transaction };
|
90
|
+
delete txWithoutFees.fees;
|
91
|
+
|
92
|
+
const signOperation = genericSignOperation(network, kind)(mockSignerContext);
|
93
|
+
const observable = signOperation({ account, transaction: txWithoutFees, deviceId });
|
94
|
+
|
95
|
+
await expect(observable.toPromise()).rejects.toThrow(FeeNotLoaded);
|
96
|
+
});
|
97
|
+
});
|
@@ -0,0 +1,65 @@
|
|
1
|
+
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
|
2
|
+
import { Account, Operation, OperationType, TransactionCommon } from "@ledgerhq/types-live";
|
3
|
+
import {
|
4
|
+
Operation as CoreOperation,
|
5
|
+
Asset,
|
6
|
+
TransactionIntent,
|
7
|
+
} from "@ledgerhq/coin-framework/api/types";
|
8
|
+
import BigNumber from "bignumber.js";
|
9
|
+
import { fromBigNumberToBigInt } from "@ledgerhq/coin-framework/utils";
|
10
|
+
|
11
|
+
export function adaptCoreOperationToLiveOperation(
|
12
|
+
accountId: string,
|
13
|
+
op: CoreOperation<Asset>,
|
14
|
+
): Operation {
|
15
|
+
return {
|
16
|
+
id: encodeOperationId(accountId, op.tx.hash, op.type),
|
17
|
+
hash: op.tx.hash,
|
18
|
+
accountId,
|
19
|
+
type: op.type as OperationType,
|
20
|
+
value: new BigNumber(op.value.toString()),
|
21
|
+
fee: new BigNumber(op.tx.fees.toString()),
|
22
|
+
blockHash: op.tx.block.hash,
|
23
|
+
blockHeight: op.tx.block.height,
|
24
|
+
senders: op.senders,
|
25
|
+
recipients: op.recipients,
|
26
|
+
date: op.tx.date,
|
27
|
+
transactionSequenceNumber: op.details?.sequence as number,
|
28
|
+
extra: {},
|
29
|
+
};
|
30
|
+
}
|
31
|
+
|
32
|
+
export function transactionToIntent(
|
33
|
+
account: Account,
|
34
|
+
transaction: TransactionCommon,
|
35
|
+
): TransactionIntent<any> {
|
36
|
+
return {
|
37
|
+
type: "Payment",
|
38
|
+
sender: account.freshAddress,
|
39
|
+
recipient: transaction.recipient,
|
40
|
+
amount: fromBigNumberToBigInt(transaction.amount, BigInt(0)),
|
41
|
+
asset: null,
|
42
|
+
};
|
43
|
+
}
|
44
|
+
|
45
|
+
export const buildOptimisticOperation = (
|
46
|
+
account: Account,
|
47
|
+
transaction: TransactionCommon,
|
48
|
+
sequenceNumber?: number,
|
49
|
+
): Operation => {
|
50
|
+
return {
|
51
|
+
id: encodeOperationId(account.id, "", "OUT"),
|
52
|
+
hash: "",
|
53
|
+
type: "OUT",
|
54
|
+
value: transaction.amount,
|
55
|
+
fee: transaction["fees"] ?? BigNumber(0),
|
56
|
+
blockHash: null,
|
57
|
+
blockHeight: null,
|
58
|
+
senders: [account.freshAddress.toString()],
|
59
|
+
recipients: [transaction.recipient],
|
60
|
+
transactionSequenceNumber: sequenceNumber ?? 0,
|
61
|
+
accountId: account.id,
|
62
|
+
date: new Date(),
|
63
|
+
extra: {},
|
64
|
+
};
|
65
|
+
};
|
package/src/bridge/impl.ts
CHANGED
@@ -6,6 +6,16 @@ import jsBridges from "../generated/bridge/js";
|
|
6
6
|
import mockBridges from "../generated/bridge/mock";
|
7
7
|
import type { CryptoCurrency } from "@ledgerhq/types-cryptoassets";
|
8
8
|
import { Account, AccountBridge, AccountLike, CurrencyBridge } from "@ledgerhq/types-live";
|
9
|
+
import { getAlpacaAccountBridge } from "./generic-alpaca/accountBridge";
|
10
|
+
import { getAlpacaCurrencyBridge } from "./generic-alpaca/currencyBridge";
|
11
|
+
|
12
|
+
const alpacaized = {
|
13
|
+
xrp: true,
|
14
|
+
};
|
15
|
+
|
16
|
+
// let accountBridgeInstance: AccountBridge<any> | null = null;
|
17
|
+
const bridgeCache: Record<string, AccountBridge<any>> = {};
|
18
|
+
let currencyBridgeInstance: CurrencyBridge | null = null;
|
9
19
|
|
10
20
|
export const getCurrencyBridge = (currency: CryptoCurrency): CurrencyBridge => {
|
11
21
|
if (getEnv("MOCK")) {
|
@@ -16,6 +26,13 @@ export const getCurrencyBridge = (currency: CryptoCurrency): CurrencyBridge => {
|
|
16
26
|
});
|
17
27
|
}
|
18
28
|
|
29
|
+
if (alpacaized[currency.family]) {
|
30
|
+
if (!currencyBridgeInstance) {
|
31
|
+
currencyBridgeInstance = getAlpacaCurrencyBridge(currency.family, "local");
|
32
|
+
}
|
33
|
+
return currencyBridgeInstance;
|
34
|
+
}
|
35
|
+
|
19
36
|
const jsBridge = jsBridges[currency.family];
|
20
37
|
if (jsBridge) {
|
21
38
|
return jsBridge.currencyBridge;
|
@@ -57,9 +74,16 @@ export function getAccountBridgeByFamily(family: string, accountId?: string): Ac
|
|
57
74
|
}
|
58
75
|
}
|
59
76
|
|
77
|
+
if (alpacaized[family]) {
|
78
|
+
if (!bridgeCache[family]) {
|
79
|
+
bridgeCache[family] = getAlpacaAccountBridge(family, "local");
|
80
|
+
}
|
81
|
+
return bridgeCache[family];
|
82
|
+
}
|
83
|
+
|
60
84
|
const jsBridge = jsBridges[family];
|
61
85
|
if (!jsBridge) {
|
62
|
-
throw new CurrencyNotSupported("
|
86
|
+
throw new CurrencyNotSupported("account bridge not found " + family);
|
63
87
|
}
|
64
88
|
return jsBridge.accountBridge;
|
65
89
|
}
|
@@ -247,6 +247,15 @@ describe("fetchAndMergeProviderData", () => {
|
|
247
247
|
),
|
248
248
|
version: 1,
|
249
249
|
},
|
250
|
+
velora: {
|
251
|
+
type: "DEX",
|
252
|
+
useInExchangeApp: false,
|
253
|
+
displayName: "Velora",
|
254
|
+
termsOfUseUrl: "https://files.paraswap.io/tos_v4.pdf",
|
255
|
+
supportUrl: "https://help.paraswap.io/en/",
|
256
|
+
mainUrl: "https://www.velora.xyz/",
|
257
|
+
needsKYC: false,
|
258
|
+
},
|
250
259
|
});
|
251
260
|
});
|
252
261
|
});
|
@@ -194,6 +194,14 @@ const DEFAULT_SWAP_PROVIDERS: Record<string, ProviderConfig & Partial<Additional
|
|
194
194
|
"hex",
|
195
195
|
),
|
196
196
|
},
|
197
|
+
velora: {
|
198
|
+
type: "DEX",
|
199
|
+
needsKYC: false,
|
200
|
+
needsBearerToken: false,
|
201
|
+
termsOfUseUrl: "https://files.paraswap.io/tos_v4.pdf",
|
202
|
+
supportUrl: "https://help.paraswap.io/en/",
|
203
|
+
mainUrl: "https://www.velora.xyz/",
|
204
|
+
},
|
197
205
|
};
|
198
206
|
|
199
207
|
export const dexProvidersContractAddress: { [key: string]: string } = {
|
@@ -359,8 +359,8 @@ const evmConfig: CurrencyLiveConfigDefinition = {
|
|
359
359
|
uri: "https://rpcapi.fantom.network",
|
360
360
|
},
|
361
361
|
explorer: {
|
362
|
-
type: "
|
363
|
-
uri: "https://
|
362
|
+
type: "blockscout",
|
363
|
+
uri: "https://ftmscout.com/api",
|
364
364
|
},
|
365
365
|
showNfts: false,
|
366
366
|
},
|