@shapeshiftoss/swapper 17.0.1 → 17.1.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/dist/swappers/thorchain/utils/makeSwapMemo/assertIsValidMemo.d.ts +3 -0
- package/dist/swappers/thorchain/utils/makeSwapMemo/assertIsValidMemo.js +66 -0
- package/dist/swappers/thorchain/utils/makeSwapMemo/makeSwapMemo.d.ts +15 -4
- package/dist/swappers/thorchain/utils/makeSwapMemo/makeSwapMemo.js +44 -23
- package/package.json +1 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.assertIsValidMemo = exports.isValidMemoAddress = void 0;
|
|
7
|
+
const caip_1 = require("@shapeshiftoss/caip");
|
|
8
|
+
const chain_adapters_1 = require("@shapeshiftoss/chain-adapters");
|
|
9
|
+
const multicoin_address_validator_1 = __importDefault(require("multicoin-address-validator"));
|
|
10
|
+
const api_1 = require("../../../../api");
|
|
11
|
+
const thorChainAssetToChainId = new Map([
|
|
12
|
+
['ETH', caip_1.ethChainId],
|
|
13
|
+
['AVAX', caip_1.avalancheChainId],
|
|
14
|
+
['BTC', caip_1.btcChainId],
|
|
15
|
+
['BCH', caip_1.bchChainId],
|
|
16
|
+
['LTC', caip_1.ltcChainId],
|
|
17
|
+
['BNB', caip_1.binanceChainId],
|
|
18
|
+
['DOGE', caip_1.dogeChainId],
|
|
19
|
+
['GAIA', caip_1.cosmosChainId],
|
|
20
|
+
['RUNE', caip_1.thorchainChainId],
|
|
21
|
+
]);
|
|
22
|
+
const isValidMemoAddress = (chainId, thorId, address) => {
|
|
23
|
+
switch (true) {
|
|
24
|
+
case thorId.startsWith('ETH.'):
|
|
25
|
+
case thorId.startsWith('AVAX.'):
|
|
26
|
+
case thorId.startsWith('BTC.'):
|
|
27
|
+
case thorId.startsWith('BCH.'):
|
|
28
|
+
case thorId.startsWith('LTC.'):
|
|
29
|
+
case thorId.startsWith('BNB.'):
|
|
30
|
+
case thorId.startsWith('DOGE.'): {
|
|
31
|
+
const chainLabel = (0, chain_adapters_1.chainIdToChainLabel)(chainId);
|
|
32
|
+
return multicoin_address_validator_1.default.validate(address, chainLabel);
|
|
33
|
+
}
|
|
34
|
+
case thorId.startsWith('GAIA.'):
|
|
35
|
+
return address.startsWith('cosmos');
|
|
36
|
+
case thorId.startsWith('RUNE.'):
|
|
37
|
+
return address.startsWith('thor');
|
|
38
|
+
default:
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
exports.isValidMemoAddress = isValidMemoAddress;
|
|
43
|
+
const assertIsValidMemo = (memo) => {
|
|
44
|
+
// BTC (and likely other utxo coins) can only support up to 80 character (byte) memos
|
|
45
|
+
const MAX_MEMO_LENGTH = 80;
|
|
46
|
+
const MEMO_PART_DELIMITER = ':';
|
|
47
|
+
const POOL_PART_DELIMITER = '.';
|
|
48
|
+
const memoParts = memo.split(MEMO_PART_DELIMITER);
|
|
49
|
+
const pool = memoParts[1];
|
|
50
|
+
const address = memoParts[2];
|
|
51
|
+
const buyAssetChainId = thorChainAssetToChainId.get(pool.split(POOL_PART_DELIMITER)[0]);
|
|
52
|
+
const isAddressValid = buyAssetChainId
|
|
53
|
+
? (0, exports.isValidMemoAddress)(buyAssetChainId, pool, address)
|
|
54
|
+
: undefined;
|
|
55
|
+
if (!isAddressValid) {
|
|
56
|
+
throw new api_1.SwapError(`[makeSwapMemo] - memo ${memo} invalid`, {
|
|
57
|
+
code: api_1.SwapErrorType.MAKE_MEMO_FAILED,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (memo.length > MAX_MEMO_LENGTH) {
|
|
61
|
+
throw new api_1.SwapError(`[makeSwapMemo] - memo length exceeds ${MAX_MEMO_LENGTH} characters`, {
|
|
62
|
+
code: api_1.SwapErrorType.MAKE_MEMO_FAILED,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
exports.assertIsValidMemo = assertIsValidMemo;
|
|
@@ -1,9 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
* https://dev.thorchain.org/thorchain-dev/memos#
|
|
2
|
+
* definition of THORChain asset notation
|
|
3
|
+
* https://dev.thorchain.org/thorchain-dev/concepts/memos#asset-notation
|
|
4
|
+
*
|
|
5
|
+
* e.g. BTC/BTC (bitcoin synth) - unaffected by this function
|
|
6
|
+
* e.g. ETH.USDT-0xdac17f958d2ee523a2206206994597c13d831ec7 (usdt on ethereum) - abbreviated by this function
|
|
4
7
|
*/
|
|
5
|
-
export declare const
|
|
8
|
+
export declare const abbreviateThorAssetId: (fullThorAssetId: string) => string;
|
|
9
|
+
declare type MakeSwapMemoArgs = {
|
|
6
10
|
buyAssetId: string;
|
|
7
11
|
destinationAddress: string;
|
|
8
12
|
limit: string;
|
|
9
|
-
}
|
|
13
|
+
};
|
|
14
|
+
declare type MakeSwapMemo = (args: MakeSwapMemoArgs) => string;
|
|
15
|
+
/**
|
|
16
|
+
* @returns thorchain memo shortened to a max of 80 characters as described:
|
|
17
|
+
* https://dev.thorchain.org/thorchain-dev/memos#mechanism-for-transaction-intent
|
|
18
|
+
*/
|
|
19
|
+
export declare const makeSwapMemo: MakeSwapMemo;
|
|
20
|
+
export {};
|
|
@@ -1,22 +1,55 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.makeSwapMemo = void 0;
|
|
3
|
+
exports.makeSwapMemo = exports.abbreviateThorAssetId = void 0;
|
|
4
4
|
const caip_1 = require("@shapeshiftoss/caip");
|
|
5
5
|
const api_1 = require("../../../../api");
|
|
6
6
|
const constants_1 = require("../constants");
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const assertIsValidMemo_1 = require("./assertIsValidMemo");
|
|
8
|
+
/**
|
|
9
|
+
* definition of THORChain asset notation
|
|
10
|
+
* https://dev.thorchain.org/thorchain-dev/concepts/memos#asset-notation
|
|
11
|
+
*
|
|
12
|
+
* e.g. BTC/BTC (bitcoin synth) - unaffected by this function
|
|
13
|
+
* e.g. ETH.USDT-0xdac17f958d2ee523a2206206994597c13d831ec7 (usdt on ethereum) - abbreviated by this function
|
|
14
|
+
*/
|
|
15
|
+
const abbreviateThorAssetId = (fullThorAssetId) => {
|
|
16
|
+
const CONTRACT_ADDRESS_DELIMITER = '-';
|
|
17
|
+
const [existingPrefix, contractAddress] = fullThorAssetId.split(CONTRACT_ADDRESS_DELIMITER);
|
|
18
|
+
// we can't shorten any asset that doesn't have a contract address
|
|
19
|
+
if (!contractAddress)
|
|
20
|
+
return fullThorAssetId;
|
|
21
|
+
/**
|
|
22
|
+
* https://dev.thorchain.org/thorchain-dev/concepts/memos#asset-abbreviations
|
|
23
|
+
*
|
|
24
|
+
* ETH.USDT
|
|
25
|
+
* ETH.USDT-ec7 // 3 characters - "short"
|
|
26
|
+
* ETH.USDT-6994597c13d831ec7 // 17 characters - "medium"
|
|
27
|
+
* ETH.USDT-0xdac17f958d2ee523a2206206994597c13d831ec7 // 26 characters - "long"
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* for the purposes of future proofing, let's use the shortest permissible format for contract addresses
|
|
31
|
+
* this has (26 + 10)^3 = 46,656 of entropy, and per the docs, the deepest pool will be used upon a collision
|
|
32
|
+
*/
|
|
33
|
+
const SHORT_ABBREVIATION_LENGTH = 3;
|
|
34
|
+
// take the last n characters of the contract address (negative slice takes last n characters)
|
|
35
|
+
const shortenedContractAddress = contractAddress.slice(-SHORT_ABBREVIATION_LENGTH);
|
|
36
|
+
// and put it back together with the existing prefix
|
|
37
|
+
return [existingPrefix, shortenedContractAddress].join(CONTRACT_ADDRESS_DELIMITER);
|
|
38
|
+
};
|
|
39
|
+
exports.abbreviateThorAssetId = abbreviateThorAssetId;
|
|
9
40
|
// use symbol of thor Asset?
|
|
10
41
|
const runeThorId = 'RUNE';
|
|
11
42
|
/**
|
|
12
43
|
* @returns thorchain memo shortened to a max of 80 characters as described:
|
|
13
44
|
* https://dev.thorchain.org/thorchain-dev/memos#mechanism-for-transaction-intent
|
|
14
45
|
*/
|
|
15
|
-
const makeSwapMemo = ({ buyAssetId, destinationAddress, limit
|
|
46
|
+
const makeSwapMemo = ({ buyAssetId, destinationAddress, limit }) => {
|
|
16
47
|
const isRune = buyAssetId === caip_1.thorchainAssetId;
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
48
|
+
const fullThorAssetId = isRune
|
|
49
|
+
? runeThorId
|
|
50
|
+
: caip_1.adapters.assetIdToPoolAssetId({ assetId: buyAssetId });
|
|
51
|
+
if (!fullThorAssetId)
|
|
52
|
+
throw new api_1.SwapError('[makeSwapMemo] - undefined thorAssetId for given buyAssetId', {
|
|
20
53
|
code: api_1.SwapErrorType.MAKE_MEMO_FAILED,
|
|
21
54
|
details: { buyAssetId },
|
|
22
55
|
});
|
|
@@ -27,21 +60,9 @@ const makeSwapMemo = ({ buyAssetId, destinationAddress, limit, }) => {
|
|
|
27
60
|
const parsedDestinationAddress = destinationAddress.includes('bitcoincash:')
|
|
28
61
|
? destinationAddress.replace('bitcoincash:', '')
|
|
29
62
|
: destinationAddress;
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (abbreviationAmount > 39)
|
|
35
|
-
throw new api_1.SwapError('[makeSwapMemo] - too much abbreviation for accurate matching', {
|
|
36
|
-
code: api_1.SwapErrorType.MAKE_MEMO_FAILED,
|
|
37
|
-
});
|
|
38
|
-
// delimeter between ticker and id allowing us to abbreviate the id: https://dev.thorchain.org/thorchain-dev/memos#asset-notation
|
|
39
|
-
const delimeterIndex = memo.indexOf('-') + 1;
|
|
40
|
-
if (!delimeterIndex) {
|
|
41
|
-
throw new api_1.SwapError('[makeSwapMemo] - unable to abbreviate asset, no delimeter found', {
|
|
42
|
-
code: api_1.SwapErrorType.MAKE_MEMO_FAILED,
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
return memo.replace(memo.slice(delimeterIndex, delimeterIndex + abbreviationAmount), '');
|
|
63
|
+
const abbreviatedThorAssetId = (0, exports.abbreviateThorAssetId)(fullThorAssetId);
|
|
64
|
+
const memo = `s:${abbreviatedThorAssetId}:${parsedDestinationAddress}:${limit}:${constants_1.THORCHAIN_AFFILIATE_NAME}:${constants_1.THORCHAIN_AFFILIATE_BIPS}`;
|
|
65
|
+
(0, assertIsValidMemo_1.assertIsValidMemo)(memo);
|
|
66
|
+
return memo;
|
|
46
67
|
};
|
|
47
68
|
exports.makeSwapMemo = makeSwapMemo;
|
package/package.json
CHANGED