@ledgerhq/coin-stellar 0.2.0-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 +20 -0
- package/.turbo/turbo-build.log +4 -0
- package/.unimportedrc.json +35 -0
- package/CHANGELOG.md +18 -0
- package/LICENSE.txt +21 -0
- package/jest.config.js +8 -0
- package/lib/bridge/bridge.integration.test.d.ts +4 -0
- package/lib/bridge/bridge.integration.test.d.ts.map +1 -0
- package/lib/bridge/bridge.integration.test.js +317 -0
- package/lib/bridge/bridge.integration.test.js.map +1 -0
- package/lib/bridge/index.d.ts +10 -0
- package/lib/bridge/index.d.ts.map +1 -0
- package/lib/bridge/index.js +72 -0
- package/lib/bridge/index.js.map +1 -0
- package/lib/broadcast.d.ts +9 -0
- package/lib/broadcast.d.ts.map +1 -0
- package/lib/broadcast.js +26 -0
- package/lib/broadcast.js.map +1 -0
- package/lib/buildOptimisticOperation.d.ts +4 -0
- package/lib/buildOptimisticOperation.d.ts.map +1 -0
- package/lib/buildOptimisticOperation.js +72 -0
- package/lib/buildOptimisticOperation.js.map +1 -0
- package/lib/buildTransaction.d.ts +10 -0
- package/lib/buildTransaction.d.ts.map +1 -0
- package/lib/buildTransaction.js +97 -0
- package/lib/buildTransaction.js.map +1 -0
- package/lib/cli.d.ts +38 -0
- package/lib/cli.d.ts.map +1 -0
- package/lib/cli.js +83 -0
- package/lib/cli.js.map +1 -0
- package/lib/config.d.ts +5 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +17 -0
- package/lib/config.js.map +1 -0
- package/lib/createTransaction.d.ts +10 -0
- package/lib/createTransaction.d.ts.map +1 -0
- package/lib/createTransaction.js +26 -0
- package/lib/createTransaction.js.map +1 -0
- package/lib/deviceTransactionConfig.d.ts +24 -0
- package/lib/deviceTransactionConfig.d.ts.map +1 -0
- package/lib/deviceTransactionConfig.js +41 -0
- package/lib/deviceTransactionConfig.js.map +1 -0
- package/lib/errors.d.ts +37 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +17 -0
- package/lib/errors.js.map +1 -0
- package/lib/estimateMaxSpendable.d.ts +5 -0
- package/lib/estimateMaxSpendable.d.ts.map +1 -0
- package/lib/estimateMaxSpendable.js +32 -0
- package/lib/estimateMaxSpendable.js.map +1 -0
- package/lib/getTransactionStatus.d.ts +5 -0
- package/lib/getTransactionStatus.d.ts.map +1 -0
- package/lib/getTransactionStatus.js +170 -0
- package/lib/getTransactionStatus.js.map +1 -0
- package/lib/hw-getAddress.d.ts +6 -0
- package/lib/hw-getAddress.d.ts.map +1 -0
- package/lib/hw-getAddress.js +28 -0
- package/lib/hw-getAddress.js.map +1 -0
- package/lib/logic.d.ts +36 -0
- package/lib/logic.d.ts.map +1 -0
- package/lib/logic.js +289 -0
- package/lib/logic.js.map +1 -0
- package/lib/network/horizon.d.ts +71 -0
- package/lib/network/horizon.d.ts.map +1 -0
- package/lib/network/horizon.js +300 -0
- package/lib/network/horizon.js.map +1 -0
- package/lib/network/index.d.ts +2 -0
- package/lib/network/index.d.ts.map +1 -0
- package/lib/network/index.js +20 -0
- package/lib/network/index.js.map +1 -0
- package/lib/prepareTransaction.d.ts +5 -0
- package/lib/prepareTransaction.d.ts.map +1 -0
- package/lib/prepareTransaction.js +41 -0
- package/lib/prepareTransaction.js.map +1 -0
- package/lib/signOperation.d.ts +6 -0
- package/lib/signOperation.d.ts.map +1 -0
- package/lib/signOperation.js +56 -0
- package/lib/signOperation.js.map +1 -0
- package/lib/specs.d.ts +7 -0
- package/lib/specs.d.ts.map +1 -0
- package/lib/specs.js +234 -0
- package/lib/specs.js.map +1 -0
- package/lib/speculos-deviceActions.d.ts +4 -0
- package/lib/speculos-deviceActions.d.ts.map +1 -0
- package/lib/speculos-deviceActions.js +99 -0
- package/lib/speculos-deviceActions.js.map +1 -0
- package/lib/synchronization.d.ts +4 -0
- package/lib/synchronization.d.ts.map +1 -0
- package/lib/synchronization.js +73 -0
- package/lib/synchronization.js.map +1 -0
- package/lib/tokens.d.ts +12 -0
- package/lib/tokens.d.ts.map +1 -0
- package/lib/tokens.js +58 -0
- package/lib/tokens.js.map +1 -0
- package/lib/transaction.d.ts +15 -0
- package/lib/transaction.d.ts.map +1 -0
- package/lib/transaction.js +63 -0
- package/lib/transaction.js.map +1 -0
- package/lib/types/index.d.ts +89 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +26 -0
- package/lib/types/index.js.map +1 -0
- package/lib/types/signer.d.ts +10 -0
- package/lib/types/signer.d.ts.map +1 -0
- package/lib/types/signer.js +3 -0
- package/lib/types/signer.js.map +1 -0
- package/lib-es/bridge/bridge.integration.test.d.ts +4 -0
- package/lib-es/bridge/bridge.integration.test.d.ts.map +1 -0
- package/lib-es/bridge/bridge.integration.test.js +311 -0
- package/lib-es/bridge/bridge.integration.test.js.map +1 -0
- package/lib-es/bridge/index.d.ts +10 -0
- package/lib-es/bridge/index.d.ts.map +1 -0
- package/lib-es/bridge/index.js +65 -0
- package/lib-es/bridge/index.js.map +1 -0
- package/lib-es/broadcast.d.ts +9 -0
- package/lib-es/broadcast.d.ts.map +1 -0
- package/lib-es/broadcast.js +22 -0
- package/lib-es/broadcast.js.map +1 -0
- package/lib-es/buildOptimisticOperation.d.ts +4 -0
- package/lib-es/buildOptimisticOperation.d.ts.map +1 -0
- package/lib-es/buildOptimisticOperation.js +65 -0
- package/lib-es/buildOptimisticOperation.js.map +1 -0
- package/lib-es/buildTransaction.d.ts +10 -0
- package/lib-es/buildTransaction.d.ts.map +1 -0
- package/lib-es/buildTransaction.js +90 -0
- package/lib-es/buildTransaction.js.map +1 -0
- package/lib-es/cli.d.ts +38 -0
- package/lib-es/cli.d.ts.map +1 -0
- package/lib-es/cli.js +77 -0
- package/lib-es/cli.js.map +1 -0
- package/lib-es/config.d.ts +5 -0
- package/lib-es/config.d.ts.map +1 -0
- package/lib-es/config.js +12 -0
- package/lib-es/config.js.map +1 -0
- package/lib-es/createTransaction.d.ts +10 -0
- package/lib-es/createTransaction.d.ts.map +1 -0
- package/lib-es/createTransaction.js +22 -0
- package/lib-es/createTransaction.js.map +1 -0
- package/lib-es/deviceTransactionConfig.d.ts +24 -0
- package/lib-es/deviceTransactionConfig.d.ts.map +1 -0
- package/lib-es/deviceTransactionConfig.js +39 -0
- package/lib-es/deviceTransactionConfig.js.map +1 -0
- package/lib-es/errors.d.ts +37 -0
- package/lib-es/errors.d.ts.map +1 -0
- package/lib-es/errors.js +14 -0
- package/lib-es/errors.js.map +1 -0
- package/lib-es/estimateMaxSpendable.d.ts +5 -0
- package/lib-es/estimateMaxSpendable.d.ts.map +1 -0
- package/lib-es/estimateMaxSpendable.js +25 -0
- package/lib-es/estimateMaxSpendable.js.map +1 -0
- package/lib-es/getTransactionStatus.d.ts +5 -0
- package/lib-es/getTransactionStatus.d.ts.map +1 -0
- package/lib-es/getTransactionStatus.js +166 -0
- package/lib-es/getTransactionStatus.js.map +1 -0
- package/lib-es/hw-getAddress.d.ts +6 -0
- package/lib-es/hw-getAddress.d.ts.map +1 -0
- package/lib-es/hw-getAddress.js +26 -0
- package/lib-es/hw-getAddress.js.map +1 -0
- package/lib-es/logic.d.ts +36 -0
- package/lib-es/logic.d.ts.map +1 -0
- package/lib-es/logic.js +274 -0
- package/lib-es/logic.js.map +1 -0
- package/lib-es/network/horizon.d.ts +71 -0
- package/lib-es/network/horizon.d.ts.map +1 -0
- package/lib-es/network/horizon.js +285 -0
- package/lib-es/network/horizon.js.map +1 -0
- package/lib-es/network/index.d.ts +2 -0
- package/lib-es/network/index.d.ts.map +1 -0
- package/lib-es/network/index.js +2 -0
- package/lib-es/network/index.js.map +1 -0
- package/lib-es/prepareTransaction.d.ts +5 -0
- package/lib-es/prepareTransaction.d.ts.map +1 -0
- package/lib-es/prepareTransaction.js +34 -0
- package/lib-es/prepareTransaction.js.map +1 -0
- package/lib-es/signOperation.d.ts +6 -0
- package/lib-es/signOperation.d.ts.map +1 -0
- package/lib-es/signOperation.js +52 -0
- package/lib-es/signOperation.js.map +1 -0
- package/lib-es/specs.d.ts +7 -0
- package/lib-es/specs.d.ts.map +1 -0
- package/lib-es/specs.js +229 -0
- package/lib-es/specs.js.map +1 -0
- package/lib-es/speculos-deviceActions.d.ts +4 -0
- package/lib-es/speculos-deviceActions.d.ts.map +1 -0
- package/lib-es/speculos-deviceActions.js +96 -0
- package/lib-es/speculos-deviceActions.js.map +1 -0
- package/lib-es/synchronization.d.ts +4 -0
- package/lib-es/synchronization.d.ts.map +1 -0
- package/lib-es/synchronization.js +69 -0
- package/lib-es/synchronization.js.map +1 -0
- package/lib-es/tokens.d.ts +12 -0
- package/lib-es/tokens.d.ts.map +1 -0
- package/lib-es/tokens.js +50 -0
- package/lib-es/tokens.js.map +1 -0
- package/lib-es/transaction.d.ts +15 -0
- package/lib-es/transaction.d.ts.map +1 -0
- package/lib-es/transaction.js +59 -0
- package/lib-es/transaction.js.map +1 -0
- package/lib-es/types/index.d.ts +89 -0
- package/lib-es/types/index.d.ts.map +1 -0
- package/lib-es/types/index.js +9 -0
- package/lib-es/types/index.js.map +1 -0
- package/lib-es/types/signer.d.ts +10 -0
- package/lib-es/types/signer.d.ts.map +1 -0
- package/lib-es/types/signer.js +2 -0
- package/lib-es/types/signer.js.map +1 -0
- package/package.json +80 -0
- package/src/bridge/bridge.integration.test.ts +373 -0
- package/src/bridge/index.ts +77 -0
- package/src/broadcast.ts +20 -0
- package/src/buildOptimisticOperation.ts +63 -0
- package/src/buildTransaction.ts +106 -0
- package/src/cli.ts +107 -0
- package/src/config.ts +18 -0
- package/src/createTransaction.ts +25 -0
- package/src/deviceTransactionConfig.ts +75 -0
- package/src/errors.ts +20 -0
- package/src/estimateMaxSpendable.ts +29 -0
- package/src/getTransactionStatus.ts +207 -0
- package/src/hw-getAddress.ts +24 -0
- package/src/logic.ts +371 -0
- package/src/network/horizon.ts +352 -0
- package/src/network/index.ts +17 -0
- package/src/prepareTransaction.ts +35 -0
- package/src/signOperation.ts +58 -0
- package/src/specs.ts +290 -0
- package/src/speculos-deviceActions.ts +117 -0
- package/src/synchronization.ts +80 -0
- package/src/tokens.ts +98 -0
- package/src/transaction.ts +99 -0
- package/src/types/index.ts +112 -0
- package/src/types/signer.ts +9 -0
- package/tsconfig.json +13 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { BigNumber } from "bignumber.js";
|
|
2
|
+
import { formatTransactionStatus } from "@ledgerhq/coin-framework/formatters";
|
|
3
|
+
import {
|
|
4
|
+
fromTransactionCommonRaw,
|
|
5
|
+
fromTransactionStatusRawCommon as fromTransactionStatusRaw,
|
|
6
|
+
toTransactionCommonRaw,
|
|
7
|
+
toTransactionStatusRawCommon as toTransactionStatusRaw,
|
|
8
|
+
} from "@ledgerhq/coin-framework/serialization";
|
|
9
|
+
import type { Account } from "@ledgerhq/types-live";
|
|
10
|
+
import { formatCurrencyUnit } from "@ledgerhq/coin-framework/currencies/formatCurrencyUnit";
|
|
11
|
+
import { getAccountCurrency } from "@ledgerhq/coin-framework/account/helpers";
|
|
12
|
+
import { getAssetCodeIssuer } from "./logic";
|
|
13
|
+
import type { Transaction, TransactionRaw } from "./types";
|
|
14
|
+
|
|
15
|
+
export function formatTransaction(
|
|
16
|
+
{ amount, recipient, fees, memoValue, useAllAmount, subAccountId }: Transaction,
|
|
17
|
+
mainAccount: Account,
|
|
18
|
+
): string {
|
|
19
|
+
const account =
|
|
20
|
+
(subAccountId && (mainAccount.subAccounts || []).find(a => a.id === subAccountId)) ||
|
|
21
|
+
mainAccount;
|
|
22
|
+
|
|
23
|
+
return `
|
|
24
|
+
SEND ${
|
|
25
|
+
useAllAmount
|
|
26
|
+
? "MAX"
|
|
27
|
+
: formatCurrencyUnit(getAccountCurrency(account).units[0], amount, {
|
|
28
|
+
showCode: true,
|
|
29
|
+
disableRounding: true,
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
TO ${recipient}
|
|
33
|
+
with fees=${
|
|
34
|
+
!fees
|
|
35
|
+
? "?"
|
|
36
|
+
: formatCurrencyUnit(getAccountCurrency(account).units[0], fees, {
|
|
37
|
+
showCode: true,
|
|
38
|
+
disableRounding: true,
|
|
39
|
+
})
|
|
40
|
+
}${memoValue ? "\n memo=" + memoValue : ""}`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function fromTransactionRaw(tr: TransactionRaw): Transaction {
|
|
44
|
+
const common = fromTransactionCommonRaw(tr);
|
|
45
|
+
const { networkInfo } = tr;
|
|
46
|
+
const [assetCode, assetIssuer] = getAssetCodeIssuer(tr);
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
...common,
|
|
50
|
+
family: tr.family,
|
|
51
|
+
fees: tr.fees ? new BigNumber(tr.fees) : null,
|
|
52
|
+
baseReserve: tr.baseReserve ? new BigNumber(tr.baseReserve) : null,
|
|
53
|
+
memoValue: tr.memoValue ? tr.memoValue : null,
|
|
54
|
+
memoType: tr.memoType ? tr.memoType : null,
|
|
55
|
+
networkInfo: networkInfo && {
|
|
56
|
+
family: networkInfo.family,
|
|
57
|
+
fees: new BigNumber(networkInfo.fees),
|
|
58
|
+
baseFee: new BigNumber(networkInfo.baseFee),
|
|
59
|
+
baseReserve: new BigNumber(networkInfo.baseReserve),
|
|
60
|
+
networkCongestionLevel: networkInfo.networkCongestionLevel,
|
|
61
|
+
},
|
|
62
|
+
mode: tr.mode,
|
|
63
|
+
assetCode,
|
|
64
|
+
assetIssuer,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function toTransactionRaw(transaction: Transaction): TransactionRaw {
|
|
69
|
+
const common = toTransactionCommonRaw(transaction);
|
|
70
|
+
const { networkInfo } = transaction;
|
|
71
|
+
const [assetCode, assetIssuer] = getAssetCodeIssuer(transaction);
|
|
72
|
+
return {
|
|
73
|
+
...common,
|
|
74
|
+
family: transaction.family,
|
|
75
|
+
fees: transaction.fees ? transaction.fees.toString() : null,
|
|
76
|
+
baseReserve: transaction.baseReserve ? transaction.baseReserve.toString() : null,
|
|
77
|
+
memoValue: transaction.memoValue ? transaction.memoValue.toString() : null,
|
|
78
|
+
memoType: transaction.memoType ? transaction.memoType.toString() : null,
|
|
79
|
+
networkInfo: networkInfo && {
|
|
80
|
+
family: networkInfo.family,
|
|
81
|
+
fees: networkInfo.fees.toString(),
|
|
82
|
+
baseFee: networkInfo.baseFee.toString(),
|
|
83
|
+
baseReserve: networkInfo.baseReserve.toString(),
|
|
84
|
+
networkCongestionLevel: networkInfo.networkCongestionLevel,
|
|
85
|
+
},
|
|
86
|
+
mode: transaction.mode,
|
|
87
|
+
assetCode,
|
|
88
|
+
assetIssuer,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export default {
|
|
93
|
+
formatTransaction,
|
|
94
|
+
fromTransactionRaw,
|
|
95
|
+
toTransactionRaw,
|
|
96
|
+
fromTransactionStatusRaw,
|
|
97
|
+
toTransactionStatusRaw,
|
|
98
|
+
formatTransactionStatus,
|
|
99
|
+
};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Horizon } from "@stellar/stellar-sdk";
|
|
2
|
+
import type { BigNumber } from "bignumber.js";
|
|
3
|
+
import type {
|
|
4
|
+
Account,
|
|
5
|
+
Operation,
|
|
6
|
+
OperationType,
|
|
7
|
+
TransactionCommon,
|
|
8
|
+
TransactionCommonRaw,
|
|
9
|
+
TransactionStatusCommon,
|
|
10
|
+
TransactionStatusCommonRaw,
|
|
11
|
+
} from "@ledgerhq/types-live";
|
|
12
|
+
|
|
13
|
+
export type NetworkInfo = {
|
|
14
|
+
family: "stellar";
|
|
15
|
+
fees: BigNumber;
|
|
16
|
+
baseFee: BigNumber;
|
|
17
|
+
baseReserve: BigNumber;
|
|
18
|
+
networkCongestionLevel?: NetworkCongestionLevel | undefined;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type NetworkInfoRaw = {
|
|
22
|
+
family: "stellar";
|
|
23
|
+
fees: string;
|
|
24
|
+
baseFee: string;
|
|
25
|
+
baseReserve: string;
|
|
26
|
+
networkCongestionLevel?: NetworkCongestionLevel | undefined;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export enum NetworkCongestionLevel {
|
|
30
|
+
LOW = "LOW",
|
|
31
|
+
MEDIUM = "MEDIUM",
|
|
32
|
+
HIGH = "HIGH",
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export const StellarMemoType = ["NO_MEMO", "MEMO_TEXT", "MEMO_ID", "MEMO_HASH", "MEMO_RETURN"];
|
|
36
|
+
|
|
37
|
+
export type StellarTransactionMode = "send" | "changeTrust";
|
|
38
|
+
|
|
39
|
+
export type Transaction = TransactionCommon & {
|
|
40
|
+
family: "stellar";
|
|
41
|
+
networkInfo?: NetworkInfo | null | undefined;
|
|
42
|
+
fees?: BigNumber | null;
|
|
43
|
+
baseReserve?: BigNumber | null;
|
|
44
|
+
memoType?: string | null;
|
|
45
|
+
memoValue?: string | null;
|
|
46
|
+
mode: StellarTransactionMode;
|
|
47
|
+
assetCode?: string;
|
|
48
|
+
assetIssuer?: string;
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export type TransactionRaw = TransactionCommonRaw & {
|
|
52
|
+
family: "stellar";
|
|
53
|
+
networkInfo?: NetworkInfoRaw | null | undefined;
|
|
54
|
+
fees?: string | null;
|
|
55
|
+
baseReserve?: string | null;
|
|
56
|
+
memoType?: string | null;
|
|
57
|
+
memoValue?: string | null;
|
|
58
|
+
mode: StellarTransactionMode;
|
|
59
|
+
assetCode?: string;
|
|
60
|
+
assetIssuer?: string;
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export type BalanceAsset = {
|
|
64
|
+
balance: string;
|
|
65
|
+
limit: string;
|
|
66
|
+
buying_liabilities: string;
|
|
67
|
+
selling_liabilities: string;
|
|
68
|
+
last_modified_ledger: number;
|
|
69
|
+
is_authorized: boolean;
|
|
70
|
+
is_authorized_to_maintain_liabilities: boolean;
|
|
71
|
+
asset_type: string;
|
|
72
|
+
asset_code: string;
|
|
73
|
+
asset_issuer: string;
|
|
74
|
+
liquidity_pool_id?: string;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export type RawOperation = Horizon.ServerApi.OperationRecord & {
|
|
78
|
+
asset_code?: string;
|
|
79
|
+
asset_issuer?: string;
|
|
80
|
+
from?: string;
|
|
81
|
+
to?: string;
|
|
82
|
+
to_muxed?: string;
|
|
83
|
+
funder?: string;
|
|
84
|
+
trustor?: string;
|
|
85
|
+
account?: string;
|
|
86
|
+
transaction_successful: boolean;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export type Signer = {
|
|
90
|
+
weight: number;
|
|
91
|
+
key: string;
|
|
92
|
+
type: string;
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export type TransactionStatus = TransactionStatusCommon;
|
|
96
|
+
|
|
97
|
+
export type TransactionStatusRaw = TransactionStatusCommonRaw;
|
|
98
|
+
|
|
99
|
+
export type StellarOperation = Operation<StellarOperationExtra>;
|
|
100
|
+
|
|
101
|
+
export type StellarOperationExtra = {
|
|
102
|
+
pagingToken?: string;
|
|
103
|
+
assetCode?: string;
|
|
104
|
+
assetIssuer?: string;
|
|
105
|
+
assetAmount?: string | undefined;
|
|
106
|
+
ledgerOpType: OperationType;
|
|
107
|
+
memo?: string;
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
export type StellarAccount = Account;
|
|
111
|
+
|
|
112
|
+
export * from "./signer";
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "../../../tsconfig.base",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"declaration": true,
|
|
5
|
+
"declarationMap": true,
|
|
6
|
+
"module": "commonjs",
|
|
7
|
+
"downlevelIteration": true,
|
|
8
|
+
"lib": ["es2020", "dom"],
|
|
9
|
+
"outDir": "lib",
|
|
10
|
+
"exactOptionalPropertyTypes": true
|
|
11
|
+
},
|
|
12
|
+
"include": ["src/**/*"]
|
|
13
|
+
}
|