@keetanetwork/anchor 0.0.53 → 0.0.58
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/asset.d.ts +18 -4
- package/lib/asset.d.ts.map +1 -1
- package/lib/asset.js +18 -0
- package/lib/asset.js.map +1 -1
- package/lib/chaining-graph.cli.d.ts +2 -0
- package/lib/chaining-graph.cli.d.ts.map +1 -0
- package/lib/chaining-graph.cli.js +257 -0
- package/lib/chaining-graph.cli.js.map +1 -0
- package/lib/chaining.d.ts +247 -0
- package/lib/chaining.d.ts.map +1 -0
- package/lib/chaining.js +1187 -0
- package/lib/chaining.js.map +1 -0
- package/lib/metadata.types.d.ts +28 -0
- package/lib/metadata.types.d.ts.map +1 -0
- package/lib/metadata.types.generated.d.ts +3 -0
- package/lib/metadata.types.generated.d.ts.map +1 -0
- package/lib/metadata.types.generated.js +15 -0
- package/lib/metadata.types.generated.js.map +1 -0
- package/lib/metadata.types.js +50 -0
- package/lib/metadata.types.js.map +1 -0
- package/lib/resolver.d.ts +15 -19
- package/lib/resolver.d.ts.map +1 -1
- package/lib/resolver.js +1101 -469
- package/lib/resolver.js.map +1 -1
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
- package/services/asset-movement/client.d.ts +12 -5
- package/services/asset-movement/client.d.ts.map +1 -1
- package/services/asset-movement/client.js +190 -9
- package/services/asset-movement/client.js.map +1 -1
- package/services/asset-movement/common.d.ts +119 -60
- package/services/asset-movement/common.d.ts.map +1 -1
- package/services/asset-movement/common.generated.d.ts +48 -0
- package/services/asset-movement/common.generated.d.ts.map +1 -0
- package/services/asset-movement/common.generated.js +37425 -0
- package/services/asset-movement/common.generated.js.map +1 -0
- package/services/asset-movement/common.js +22 -35368
- package/services/asset-movement/common.js.map +1 -1
- package/services/asset-movement/lib/location.d.ts +10 -1
- package/services/asset-movement/lib/location.d.ts.map +1 -1
- package/services/asset-movement/lib/location.generated.d.ts +2 -1
- package/services/asset-movement/lib/location.generated.d.ts.map +1 -1
- package/services/asset-movement/lib/location.generated.js +23 -0
- package/services/asset-movement/lib/location.generated.js.map +1 -1
- package/services/asset-movement/lib/location.js +3 -0
- package/services/asset-movement/lib/location.js.map +1 -1
- package/services/asset-movement/server.d.ts +17 -6
- package/services/asset-movement/server.d.ts.map +1 -1
- package/services/asset-movement/server.js +47 -2
- package/services/asset-movement/server.js.map +1 -1
- package/services/fx/client.d.ts +3 -2
- package/services/fx/client.d.ts.map +1 -1
- package/services/fx/client.js +8 -3
- package/services/fx/client.js.map +1 -1
- package/services/fx/server.d.ts +2 -1
- package/services/fx/server.d.ts.map +1 -1
- package/services/fx/server.js +3 -0
- package/services/fx/server.js.map +1 -1
- package/services/storage/clients/contacts.generated.js +142 -90
- package/services/storage/clients/contacts.generated.js.map +1 -1
- package/services/storage/common.d.ts +7 -1
- package/services/storage/common.d.ts.map +1 -1
- package/services/storage/common.js.map +1 -1
- package/services/storage/server.js +1 -1
- package/services/storage/server.js.map +1 -1
- package/services/storage/test-utils.d.ts +1 -0
- package/services/storage/test-utils.d.ts.map +1 -1
- package/services/storage/test-utils.js +3 -0
- package/services/storage/test-utils.js.map +1 -1
package/lib/asset.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { TokenAddress, TokenPublicKeyString } from '@keetanetwork/keetanet-client/lib/account.js';
|
|
2
2
|
import { lib as KeetaNetLib } from '@keetanetwork/keetanet-client';
|
|
3
3
|
import * as CurrencyInfo from '@keetanetwork/currency-info';
|
|
4
|
+
import type { ChainLocationType } from '../services/asset-movement/common.js';
|
|
4
5
|
export type KeetaNetAccount = InstanceType<typeof KeetaNetLib.Account>;
|
|
5
6
|
export type KeetaNetStorageAccount = InstanceType<typeof KeetaNetLib.Account<typeof KeetaNetLib.Account.AccountKeyAlgorithm.STORAGE>>;
|
|
6
7
|
export type KeetaNetToken = InstanceType<typeof KeetaNetLib.Account<typeof KeetaNetLib.Account.AccountKeyAlgorithm.TOKEN>>;
|
|
@@ -10,10 +11,20 @@ export type CurrencySearchCanonical = CurrencyInfo.ISOCurrencyCode | `$${string}
|
|
|
10
11
|
export type CurrencySearchInput = CurrencySearchCanonical | CurrencyInfo.Currency;
|
|
11
12
|
export type TokenSearchInput = TokenAddress | TokenPublicKeyString;
|
|
12
13
|
export type TokenSearchCanonical = TokenPublicKeyString;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
type ChainAssetType = {
|
|
15
|
+
evm: HexString;
|
|
16
|
+
} & {
|
|
17
|
+
[K in 'solana' | 'bitcoin' | 'tron']: string;
|
|
18
|
+
};
|
|
19
|
+
export type ExternalChainLocationType = Exclude<ChainLocationType, 'keeta'>;
|
|
20
|
+
export type ExternalChainAsset<T extends ExternalChainLocationType = ExternalChainLocationType> = {
|
|
21
|
+
[K in T]: `${K}:${ChainAssetType[K]}`;
|
|
22
|
+
}[T];
|
|
23
|
+
export type EVMAsset = ExternalChainAsset<'evm'>;
|
|
24
|
+
export type TronAsset = ExternalChainAsset<'tron'>;
|
|
25
|
+
export type SolanaAsset = ExternalChainAsset<'solana'>;
|
|
26
|
+
export type BitcoinAsset = ExternalChainAsset<'bitcoin'>;
|
|
27
|
+
export type ChainAssetString = ExternalChainAsset | TokenPublicKeyString;
|
|
17
28
|
export type MovableAssetSearchInput = CurrencySearchInput | TokenSearchInput | ChainAssetString;
|
|
18
29
|
export type MovableAssetSearchCanonical = CurrencySearchCanonical | TokenSearchCanonical | ChainAssetString;
|
|
19
30
|
export type MovableAsset = TokenAddress | TokenPublicKeyString | CurrencySearchInput | ChainAssetString;
|
|
@@ -26,5 +37,8 @@ export declare function isTronAsset(input: unknown): input is TronAsset;
|
|
|
26
37
|
export declare function toSolanaAsset(input: string): SolanaAsset;
|
|
27
38
|
export declare function parseSolanaAsset(input: SolanaAsset): string;
|
|
28
39
|
export declare function isSolanaAsset(input: unknown): input is SolanaAsset;
|
|
40
|
+
export declare function isBitcoinAsset(input: unknown): input is BitcoinAsset;
|
|
41
|
+
export declare function isExternalChainAsset<T extends ExternalChainLocationType = ExternalChainLocationType>(input: unknown, type?: T): input is ExternalChainAsset<T>;
|
|
29
42
|
export declare function convertAssetSearchInputToCanonical(input: MovableAssetSearchInput): MovableAssetSearchCanonical;
|
|
43
|
+
export {};
|
|
30
44
|
//# sourceMappingURL=asset.d.ts.map
|
package/lib/asset.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset.d.ts","sourceRoot":"","sources":["../../src/lib/asset.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,8CAA8C,CAAC;AACvG,OAAO,EAAE,GAAG,IAAI,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,YAAY,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"asset.d.ts","sourceRoot":"","sources":["../../src/lib/asset.ts"],"names":[],"mappings":"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"}
|
package/lib/asset.js
CHANGED
|
@@ -57,6 +57,24 @@ export function parseSolanaAsset(input) {
|
|
|
57
57
|
export function isSolanaAsset(input) {
|
|
58
58
|
return (typeof input === 'string' && input.startsWith('solana:'));
|
|
59
59
|
}
|
|
60
|
+
export function isBitcoinAsset(input) {
|
|
61
|
+
return (typeof input === 'string' && input.startsWith('bitcoin:'));
|
|
62
|
+
}
|
|
63
|
+
// XXX:TODO We should eventually refactor these to be shared between location and asset, so we can have one source of truth per location
|
|
64
|
+
export function isExternalChainAsset(input, type) {
|
|
65
|
+
const checks = {
|
|
66
|
+
evm: isEVMAsset,
|
|
67
|
+
solana: isSolanaAsset,
|
|
68
|
+
tron: isTronAsset,
|
|
69
|
+
bitcoin: isBitcoinAsset
|
|
70
|
+
};
|
|
71
|
+
if (type) {
|
|
72
|
+
return (checks[type](input));
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
return (Object.values(checks).some(check => check(input)));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
60
78
|
export function convertAssetSearchInputToCanonical(input) {
|
|
61
79
|
if (input instanceof CurrencyInfo.Currency || CurrencyInfo.Currency.isCurrencyCode(input) || CurrencyInfo.Currency.isISOCurrencyNumber(input)) {
|
|
62
80
|
if (CurrencyInfo.Currency.isCurrencyCode(input)) {
|
package/lib/asset.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"asset.js","sourceRoot":"","sources":["../../src/lib/asset.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,IAAI,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,YAAY,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"asset.js","sourceRoot":"","sources":["../../src/lib/asset.ts"],"names":[],"mappings":"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","sourcesContent":["import type { TokenAddress, TokenPublicKeyString } from '@keetanetwork/keetanet-client/lib/account.js';\nimport { lib as KeetaNetLib } from '@keetanetwork/keetanet-client';\nimport * as CurrencyInfo from '@keetanetwork/currency-info';\nimport type { ChainLocationType } from '../services/asset-movement/common.js';\n\nexport type KeetaNetAccount = InstanceType<typeof KeetaNetLib.Account>;\nexport type KeetaNetStorageAccount = InstanceType<typeof KeetaNetLib.Account<typeof KeetaNetLib.Account.AccountKeyAlgorithm.STORAGE>>;\nexport type KeetaNetToken = InstanceType<typeof KeetaNetLib.Account<typeof KeetaNetLib.Account.AccountKeyAlgorithm.TOKEN>>;\nexport type KeetaNetTokenPublicKeyString = ReturnType<InstanceType<typeof KeetaNetLib.Account<typeof KeetaNetLib.Account.AccountKeyAlgorithm.TOKEN>>['publicKeyString']['get']>;\n\nexport type HexString = `0x${string}`;\n\nexport type CurrencySearchCanonical = CurrencyInfo.ISOCurrencyCode | `$${string}`; /* XXX:TODO */\nexport type CurrencySearchInput = CurrencySearchCanonical | CurrencyInfo.Currency;\n\nexport type TokenSearchInput = TokenAddress | TokenPublicKeyString;\nexport type TokenSearchCanonical = TokenPublicKeyString;\n\ntype ChainAssetType = {\n\tevm: HexString;\n} & {\n\t[K in 'solana' | 'bitcoin' | 'tron']: string;\n}\n\nexport type ExternalChainLocationType = Exclude<ChainLocationType, 'keeta'>;\nexport type ExternalChainAsset<T extends ExternalChainLocationType = ExternalChainLocationType> = {\n\t[K in T]: `${K}:${ChainAssetType[K]}`\n}[T];\n\nexport type EVMAsset = ExternalChainAsset<'evm'>;\nexport type TronAsset = ExternalChainAsset<'tron'>;\nexport type SolanaAsset = ExternalChainAsset<'solana'>;\nexport type BitcoinAsset = ExternalChainAsset<'bitcoin'>;\nexport type ChainAssetString = ExternalChainAsset | TokenPublicKeyString;\nexport type MovableAssetSearchInput = CurrencySearchInput | TokenSearchInput | ChainAssetString;\nexport type MovableAssetSearchCanonical = CurrencySearchCanonical | TokenSearchCanonical | ChainAssetString;\nexport type MovableAsset = TokenAddress | TokenPublicKeyString | CurrencySearchInput | ChainAssetString;\n\nexport function toEVMAsset(input: HexString): EVMAsset {\n\treturn(`evm:${input}`);\n}\n\nfunction isHexString(input: unknown): input is HexString {\n\tif (typeof input === 'string' && input.startsWith('0x')) {\n\t\treturn(true);\n\t}\n\n\treturn(false);\n}\n\nexport function parseEVMAsset(input: EVMAsset): HexString {\n\tconst parts = input.split(':');\n\tif (parts.length !== 2 || parts[0] !== 'evm') {\n\t\tthrow(new Error('Invalid EVMAsset string'));\n\t}\n\n\tconst value = parts[1];\n\tif (!isHexString(value)) {\n\t\tthrow(new Error('Invalid hex string in EVMAsset'));\n\t}\n\n\treturn(value);\n}\n\nexport function isEVMAsset(input: unknown): input is EVMAsset {\n\treturn(typeof input === 'string' && input.startsWith('evm:0x'));\n}\n\nexport function toTronAsset(input: string): TronAsset {\n\treturn(`tron:${input}`);\n}\n\nexport function parseTronAsset(input: TronAsset): string {\n\tconst parts = input.split(':');\n\tif (parts.length !== 2 || parts[0] !== 'tron') {\n\t\tthrow(new Error('Invalid TronAsset string'));\n\t}\n\n\tconst value = parts[1];\n\tif (!value || typeof value !== 'string' || value.length === 0) {\n\t\tthrow(new Error('Invalid hex string in TronAsset'));\n\t}\n\n\treturn(value);\n}\n\nexport function isTronAsset(input: unknown): input is TronAsset {\n\treturn(typeof input === 'string' && input.startsWith('tron:'));\n}\n\nexport function toSolanaAsset(input: string): SolanaAsset {\n\treturn(`solana:${input}`);\n}\n\nexport function parseSolanaAsset(input: SolanaAsset): string {\n\tconst parts = input.split(':');\n\tif (parts.length !== 2 || parts[0] !== 'solana') {\n\t\tthrow(new Error('Invalid SolanaAsset string'));\n\t}\n\n\tconst value = parts[1];\n\tif (!value || typeof value !== 'string' || value.length === 0) {\n\t\tthrow(new Error('Invalid string in SolanaAsset'));\n\t}\n\n\treturn(value);\n}\n\nexport function isSolanaAsset(input: unknown): input is SolanaAsset {\n\treturn(typeof input === 'string' && input.startsWith('solana:'));\n}\n\nexport function isBitcoinAsset(input: unknown): input is BitcoinAsset {\n\treturn(typeof input === 'string' && input.startsWith('bitcoin:'));\n}\n\n// XXX:TODO We should eventually refactor these to be shared between location and asset, so we can have one source of truth per location\nexport function isExternalChainAsset<T extends ExternalChainLocationType = ExternalChainLocationType>(input: unknown, type?: T): input is ExternalChainAsset<T> {\n\tconst checks: {\n\t\t[K in ExternalChainLocationType]: (input: unknown) => boolean;\n\t} = {\n\t\tevm: isEVMAsset,\n\t\tsolana: isSolanaAsset,\n\t\ttron: isTronAsset,\n\t\tbitcoin: isBitcoinAsset\n\t};\n\n\tif (type) {\n\t\treturn(checks[type](input));\n\t} else {\n\t\treturn(Object.values(checks).some(check => check(input)));\n\t}\n}\n\nexport function convertAssetSearchInputToCanonical(input: MovableAssetSearchInput): MovableAssetSearchCanonical {\n\tif (input instanceof CurrencyInfo.Currency || CurrencyInfo.Currency.isCurrencyCode(input) || CurrencyInfo.Currency.isISOCurrencyNumber(input)) {\n\t\tif (CurrencyInfo.Currency.isCurrencyCode(input)) {\n\t\t\treturn(input);\n\t\t} else if (CurrencyInfo.Currency.isISOCurrencyNumber(input)) {\n\t\t\tinput = new CurrencyInfo.Currency(input);\n\t\t}\n\n\t\treturn(input.code);\n\t} else {\n\t\tif (typeof input === 'string') {\n\t\t\treturn(input);\n\t\t}\n\n\t\tinput.assertKeyType(KeetaNetLib.Account.AccountKeyAlgorithm.TOKEN);\n\t\treturn(input.publicKeyString.get());\n\t}\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chaining-graph.cli.d.ts","sourceRoot":"","sources":["../../src/lib/chaining-graph.cli.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import * as __typia_transform__assertGuard from "typia/lib/internal/_assertGuard.js";
|
|
2
|
+
import { createAssert } from 'typia';
|
|
3
|
+
import { assertNever } from './utils/never.js';
|
|
4
|
+
import { KeetaNet } from '../client/index.js';
|
|
5
|
+
import { getDefaultResolverConfig } from '../config.js';
|
|
6
|
+
import { Resolver } from './index.js';
|
|
7
|
+
import { AnchorChaining } from './chaining.js';
|
|
8
|
+
import { convertAssetSearchInputToCanonical } from './asset.js';
|
|
9
|
+
import { convertAssetLocationToString } from '../services/asset-movement/common.js';
|
|
10
|
+
const assertNetwork = (() => { const __is = input => "main" === input || "staging" === input || "test" === input || "dev" === input; let _errorFactory; return (input, errorFactory) => {
|
|
11
|
+
if (false === __is(input)) {
|
|
12
|
+
_errorFactory = errorFactory;
|
|
13
|
+
((input, _path, _exceptionable = true) => "main" === input || "staging" === input || "test" === input || "dev" === input || __typia_transform__assertGuard._assertGuard(true, {
|
|
14
|
+
method: "createAssert",
|
|
15
|
+
path: _path + "",
|
|
16
|
+
expected: "(\"dev\" | \"main\" | \"staging\" | \"test\")",
|
|
17
|
+
value: input
|
|
18
|
+
}, _errorFactory))(input, "$input", true);
|
|
19
|
+
}
|
|
20
|
+
return input;
|
|
21
|
+
}; })();
|
|
22
|
+
function getConfig(args) {
|
|
23
|
+
const retval = {
|
|
24
|
+
network: 'test',
|
|
25
|
+
roots: [],
|
|
26
|
+
skipDefaultResolver: false,
|
|
27
|
+
showFX: false
|
|
28
|
+
};
|
|
29
|
+
let flag = null;
|
|
30
|
+
for (const arg of args) {
|
|
31
|
+
if (flag) {
|
|
32
|
+
if (flag === 'network') {
|
|
33
|
+
retval.network = assertNetwork(arg);
|
|
34
|
+
}
|
|
35
|
+
else if (flag === 'roots') {
|
|
36
|
+
const acct = KeetaNet.lib.Account.fromPublicKeyString(arg);
|
|
37
|
+
retval.roots.push(acct);
|
|
38
|
+
}
|
|
39
|
+
else {
|
|
40
|
+
assertNever(flag);
|
|
41
|
+
}
|
|
42
|
+
flag = null;
|
|
43
|
+
}
|
|
44
|
+
else if (arg.startsWith('-')) {
|
|
45
|
+
if (arg === '--network' || arg === '-n') {
|
|
46
|
+
flag = 'network';
|
|
47
|
+
}
|
|
48
|
+
else if (arg === '--root' || arg === '-r') {
|
|
49
|
+
flag = 'roots';
|
|
50
|
+
}
|
|
51
|
+
else if (arg === '--skip-default-resolver') {
|
|
52
|
+
retval.skipDefaultResolver = true;
|
|
53
|
+
}
|
|
54
|
+
else if (arg === '--show-fx' || arg === '-x') {
|
|
55
|
+
retval.showFX = true;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
throw (new Error(`Unknown flag: ${arg}`));
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
throw (new Error(`Unexpected argument: ${arg}`));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
if (flag !== null) {
|
|
66
|
+
throw (new Error(`Missing value for flag: ${flag}`));
|
|
67
|
+
}
|
|
68
|
+
return (retval);
|
|
69
|
+
}
|
|
70
|
+
async function makeGraphViz(input) {
|
|
71
|
+
const nodes = await input.graph['computeGraphNodes']();
|
|
72
|
+
// Assign stable sequential IDs to each unique (asset, location) pair
|
|
73
|
+
const dotNodeId = new Map();
|
|
74
|
+
let nextNodeId = 0;
|
|
75
|
+
function assetLocationKey(asset, location) {
|
|
76
|
+
return (`${convertAssetSearchInputToCanonical(asset)}@${convertAssetLocationToString(location)}`);
|
|
77
|
+
}
|
|
78
|
+
function getDotId(asset, location) {
|
|
79
|
+
const key = assetLocationKey(asset, location);
|
|
80
|
+
let found = dotNodeId.get(key);
|
|
81
|
+
if (!found) {
|
|
82
|
+
found = `n${nextNodeId++}`;
|
|
83
|
+
dotNodeId.set(key, found);
|
|
84
|
+
}
|
|
85
|
+
return (found);
|
|
86
|
+
}
|
|
87
|
+
for (const node of nodes) {
|
|
88
|
+
getDotId(node.from.asset, node.from.location);
|
|
89
|
+
getDotId(node.to.asset, node.to.location);
|
|
90
|
+
}
|
|
91
|
+
const currencyMapByToken = await (async () => {
|
|
92
|
+
const map = new Map();
|
|
93
|
+
const listedTokens = await input.graph.resolver.listTokens();
|
|
94
|
+
for (const asset of listedTokens) {
|
|
95
|
+
map.set(asset.token, asset.currency);
|
|
96
|
+
}
|
|
97
|
+
return (map);
|
|
98
|
+
})();
|
|
99
|
+
const publicKeyOrDefaultLabel = (input) => {
|
|
100
|
+
if (input.startsWith('keeta_')) {
|
|
101
|
+
try {
|
|
102
|
+
const pub = KeetaNet.lib.Account.toPublicKeyString(input);
|
|
103
|
+
return (`${pub.slice(0, 10)}...${pub.slice(-4)}`);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
/* ignore */
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return (input);
|
|
110
|
+
};
|
|
111
|
+
const assetLabel = (asset) => {
|
|
112
|
+
if (KeetaNet.lib.Account.isInstance(asset) || (typeof asset === 'string' && asset.startsWith('keeta_'))) {
|
|
113
|
+
const tokenPub = KeetaNet.lib.Account.toAccount(asset)
|
|
114
|
+
.assertKeyType(KeetaNet.lib.Account.AccountKeyAlgorithm.TOKEN)
|
|
115
|
+
.publicKeyString.get();
|
|
116
|
+
const cached = currencyMapByToken.get(tokenPub);
|
|
117
|
+
if (cached) {
|
|
118
|
+
return (cached);
|
|
119
|
+
}
|
|
120
|
+
return (publicKeyOrDefaultLabel(tokenPub));
|
|
121
|
+
}
|
|
122
|
+
const s = String(convertAssetSearchInputToCanonical(asset));
|
|
123
|
+
return (s.length <= 10 ? s : `\u2026${s.slice(-8)}`);
|
|
124
|
+
};
|
|
125
|
+
function esc(s) {
|
|
126
|
+
return (s.replace(/\\/g, '\\\\').replace(/"/g, '\\"'));
|
|
127
|
+
}
|
|
128
|
+
// Group (asset, location) entries by location string for clustering
|
|
129
|
+
const locationGroups = new Map();
|
|
130
|
+
for (const node of nodes) {
|
|
131
|
+
for (const side of [node.from, node.to]) {
|
|
132
|
+
const locStr = convertAssetLocationToString(side.location);
|
|
133
|
+
if (!locationGroups.has(locStr)) {
|
|
134
|
+
locationGroups.set(locStr, []);
|
|
135
|
+
}
|
|
136
|
+
const group = locationGroups.get(locStr);
|
|
137
|
+
if (!group) {
|
|
138
|
+
throw (new Error(`Unexpected missing location group for location string: ${locStr}`));
|
|
139
|
+
}
|
|
140
|
+
const key = assetLocationKey(side.asset, side.location);
|
|
141
|
+
if (!group.some(g => assetLocationKey(g.asset, g.location) === key)) {
|
|
142
|
+
group.push({ asset: side.asset, location: side.location });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const lines = [
|
|
147
|
+
'digraph AnchorGraph {',
|
|
148
|
+
' rankdir=LR',
|
|
149
|
+
' node [shape=box, style=filled, fontname="Helvetica"]',
|
|
150
|
+
' edge [fontsize=9, fontname="Helvetica"]',
|
|
151
|
+
''
|
|
152
|
+
];
|
|
153
|
+
// One cluster per location color-coded by location type
|
|
154
|
+
let clusterIdx = 0;
|
|
155
|
+
for (const [locStr, entries] of locationGroups) {
|
|
156
|
+
const isKeeta = locStr.startsWith('chain:keeta:');
|
|
157
|
+
const isExtChain = !isKeeta && locStr.startsWith('chain:');
|
|
158
|
+
// Keeta = blue tint, fiat/bank = green tint, other external chains = red tint
|
|
159
|
+
const clusterFill = isKeeta ? '#e8f4ff' : isExtChain ? '#fff0f0' : '#f0fff0';
|
|
160
|
+
const nodeFill = isKeeta ? '#fffacd' : isExtChain ? '#ffe4e1' : '#e0ffe0';
|
|
161
|
+
lines.push(` subgraph cluster_${clusterIdx++} {`);
|
|
162
|
+
lines.push(` label="${esc(locStr)}"`);
|
|
163
|
+
lines.push(` style=filled`);
|
|
164
|
+
lines.push(` color="#aaaaaa"`);
|
|
165
|
+
lines.push(` fillcolor="${clusterFill}"`);
|
|
166
|
+
for (const { asset, location } of entries) {
|
|
167
|
+
const id = getDotId(asset, location);
|
|
168
|
+
const label = assetLabel(asset);
|
|
169
|
+
const tooltip = esc(assetLocationKey(asset, location));
|
|
170
|
+
lines.push(` ${id} [label="${esc(label)}", fillcolor="${nodeFill}", tooltip="${tooltip}"]`);
|
|
171
|
+
}
|
|
172
|
+
lines.push(' }');
|
|
173
|
+
lines.push('');
|
|
174
|
+
}
|
|
175
|
+
function isFXLike(node) {
|
|
176
|
+
if (node.type === 'fx') {
|
|
177
|
+
return (true);
|
|
178
|
+
}
|
|
179
|
+
else if (node.type === 'assetMovement') {
|
|
180
|
+
if (node.from.rail === 'KEETA_SEND' && node.to.rail === 'KEETA_SEND') {
|
|
181
|
+
if (convertAssetLocationToString(node.from.location) === convertAssetLocationToString(node.to.location)) {
|
|
182
|
+
return (true);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return (false);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
assertNever(node);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const emittedFXLikeKeys = new Set();
|
|
192
|
+
const emittedMoveKeys = new Set();
|
|
193
|
+
for (const node of nodes) {
|
|
194
|
+
const fromKey = assetLocationKey(node.from.asset, node.from.location);
|
|
195
|
+
const toKey = assetLocationKey(node.to.asset, node.to.location);
|
|
196
|
+
const from = getDotId(node.from.asset, node.from.location);
|
|
197
|
+
const to = getDotId(node.to.asset, node.to.location);
|
|
198
|
+
if (isFXLike(node)) {
|
|
199
|
+
if (!input.config.showFX) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
const [lo, hi] = fromKey < toKey ? [fromKey, toKey] : [toKey, fromKey];
|
|
203
|
+
const canonKey = `${lo}|${hi}|${node.providerID}`;
|
|
204
|
+
if (emittedFXLikeKeys.has(canonKey)) {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
emittedFXLikeKeys.add(canonKey);
|
|
208
|
+
const hasReverse = nodes.some(n => isFXLike(n) &&
|
|
209
|
+
n.providerID === node.providerID &&
|
|
210
|
+
assetLocationKey(n.from.asset, n.from.location) === toKey &&
|
|
211
|
+
assetLocationKey(n.to.asset, n.to.location) === fromKey);
|
|
212
|
+
const edgeLabel = esc(`FX [PRV=${publicKeyOrDefaultLabel(node.providerID)}]`);
|
|
213
|
+
const dirAttr = hasReverse ? ', dir=both' : '';
|
|
214
|
+
lines.push(` ${from} -> FX_${esc(publicKeyOrDefaultLabel(node.providerID))} -> ${to} [label="${edgeLabel}", color=darkorange, fontcolor=darkorange, style=dashed${dirAttr}, constraint=false]`);
|
|
215
|
+
}
|
|
216
|
+
else {
|
|
217
|
+
const railLabel = node.to.rail;
|
|
218
|
+
const edgeLabel = esc(`${railLabel} [PRV=${publicKeyOrDefaultLabel(node.providerID)}]`);
|
|
219
|
+
const moveKey = `${from}|${to}|${edgeLabel}`;
|
|
220
|
+
if (emittedMoveKeys.has(moveKey)) {
|
|
221
|
+
continue;
|
|
222
|
+
}
|
|
223
|
+
emittedMoveKeys.add(moveKey);
|
|
224
|
+
lines.push(` ${from} -> ${to} [label="${edgeLabel}", color=steelblue, fontcolor=steelblue]`);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
lines.push('}');
|
|
228
|
+
return (lines.join('\n'));
|
|
229
|
+
}
|
|
230
|
+
(async () => {
|
|
231
|
+
const config = getConfig(process.argv.slice(2));
|
|
232
|
+
const fakeAccount = KeetaNet.lib.Account.fromSeed(KeetaNet.lib.Account.generateRandomSeed(), 0);
|
|
233
|
+
const userClient = KeetaNet.UserClient.fromNetwork(config.network, fakeAccount);
|
|
234
|
+
const usingRoots = config.roots;
|
|
235
|
+
const defaultConfig = getDefaultResolverConfig(userClient);
|
|
236
|
+
if (!config.skipDefaultResolver) {
|
|
237
|
+
usingRoots.push(...([defaultConfig.root].flat()));
|
|
238
|
+
}
|
|
239
|
+
const resolver = new Resolver({
|
|
240
|
+
...defaultConfig,
|
|
241
|
+
root: usingRoots
|
|
242
|
+
});
|
|
243
|
+
const chaining = new AnchorChaining({
|
|
244
|
+
client: userClient,
|
|
245
|
+
resolver: resolver
|
|
246
|
+
});
|
|
247
|
+
const computed = await makeGraphViz({
|
|
248
|
+
graph: chaining['graph'],
|
|
249
|
+
config
|
|
250
|
+
});
|
|
251
|
+
console.log(computed);
|
|
252
|
+
process.exit(0);
|
|
253
|
+
})().catch(function (err) {
|
|
254
|
+
console.error(err);
|
|
255
|
+
process.exit(1);
|
|
256
|
+
});
|
|
257
|
+
//# sourceMappingURL=chaining-graph.cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chaining-graph.cli.js","sourceRoot":"","sources":["../../src/lib/chaining-graph.cli.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Networks } from '@keetanetwork/keetanet-client/config/index.js';\nimport type { GenericAccount, TokenPublicKeyString } from '@keetanetwork/keetanet-client/lib/account.js';\nimport { createAssert } from 'typia';\nimport { assertNever } from './utils/never.js';\nimport { KeetaNet } from '../client/index.js';\nimport { getDefaultResolverConfig } from '../config.js';\nimport { Resolver } from './index.js';\nimport type { AnchorChainingAsset, GraphNodeLike } from './chaining.js';\nimport { AnchorChaining } from './chaining.js';\nimport { convertAssetSearchInputToCanonical } from './asset.js';\nimport type { AssetLocationLike } from '../services/asset-movement/common.js';\nimport { convertAssetLocationToString } from '../services/asset-movement/common.js';\n\nconst assertNetwork = createAssert<Networks>();\n\ninterface GraphCLIArgs {\n\tnetwork: Networks;\n\tskipDefaultResolver: boolean;\n\troots: GenericAccount[];\n\n\tshowFX: boolean;\n}\n\nfunction getConfig(args: string[]): GraphCLIArgs {\n\tconst retval: GraphCLIArgs = {\n\t\tnetwork: 'test',\n\t\troots: [],\n\t\tskipDefaultResolver: false,\n\t\tshowFX: false\n\t};\n\n\tlet flag: keyof GraphCLIArgs | null = null;\n\tfor (const arg of args) {\n\t\tif (flag) {\n\t\t\tif (flag === 'network') {\n\t\t\t\tretval.network = assertNetwork(arg);\n\t\t\t} else if (flag === 'roots') {\n\t\t\t\tconst acct = KeetaNet.lib.Account.fromPublicKeyString(arg);\n\t\t\t\tretval.roots.push(acct);\n\t\t\t} else {\n\t\t\t\tassertNever(flag);\n\t\t\t}\n\n\t\t\tflag = null;\n\t\t} else if (arg.startsWith('-')) {\n\t\t\tif (arg === '--network' || arg === '-n') {\n\t\t\t\tflag = 'network';\n\t\t\t} else if (arg === '--root' || arg === '-r') {\n\t\t\t\tflag = 'roots';\n\t\t\t} else if (arg === '--skip-default-resolver') {\n\t\t\t\tretval.skipDefaultResolver = true;\n\t\t\t} else if (arg === '--show-fx' || arg === '-x') {\n\t\t\t\tretval.showFX = true;\n\t\t\t} else {\n\t\t\t\tthrow(new Error(`Unknown flag: ${arg}`));\n\t\t\t}\n\t\t} else {\n\t\t\tthrow(new Error(`Unexpected argument: ${arg}`));\n\t\t}\n\t}\n\n\tif (flag !== null) {\n\t\tthrow(new Error(`Missing value for flag: ${flag}`));\n\t}\n\n\treturn(retval);\n}\n\nasync function makeGraphViz(input: {\n\tgraph: AnchorChaining['graph'];\n\tconfig: Pick<GraphCLIArgs, 'showFX'>;\n}) {\n\tconst nodes = await input.graph['computeGraphNodes']();\n\n\t// Assign stable sequential IDs to each unique (asset, location) pair\n\tconst dotNodeId = new Map<string, string>();\n\tlet nextNodeId = 0;\n\n\tfunction assetLocationKey(asset: AnchorChainingAsset, location: AssetLocationLike): string {\n\t\treturn(`${convertAssetSearchInputToCanonical(asset)}@${convertAssetLocationToString(location)}`);\n\t}\n\n\tfunction getDotId(asset: AnchorChainingAsset, location: AssetLocationLike): string {\n\t\tconst key = assetLocationKey(asset, location);\n\n\t\tlet found = dotNodeId.get(key);\n\t\tif (!found) {\n\t\t\tfound = `n${nextNodeId++}`;\n\t\t\tdotNodeId.set(key, found);\n\t\t}\n\n\t\treturn(found);\n\t}\n\n\tfor (const node of nodes) {\n\t\tgetDotId(node.from.asset, node.from.location);\n\t\tgetDotId(node.to.asset, node.to.location);\n\t}\n\n\tconst currencyMapByToken = await (async () => {\n\t\tconst map = new Map<TokenPublicKeyString, string>();\n\t\tconst listedTokens = await input.graph.resolver.listTokens();\n\t\tfor (const asset of listedTokens) {\n\t\t\tmap.set(asset.token, asset.currency);\n\t\t}\n\t\treturn(map);\n\t})();\n\n\tconst publicKeyOrDefaultLabel = (input: string) => {\n\t\tif (input.startsWith('keeta_')) {\n\t\t\ttry {\n\t\t\t\tconst pub = KeetaNet.lib.Account.toPublicKeyString(input);\n\n\t\t\t\treturn(`${pub.slice(0, 10)}...${pub.slice(-4)}`)\n\t\t\t} catch {\n\t\t\t\t/* ignore */\n\t\t\t}\n\t\t}\n\n\t\treturn(input);\n\t}\n\n\tconst assetLabel = (asset: AnchorChainingAsset): string => {\n\t\tif (KeetaNet.lib.Account.isInstance(asset) || (typeof asset === 'string' && asset.startsWith('keeta_'))) {\n\t\t\tconst tokenPub = KeetaNet.lib.Account.toAccount(asset)\n\t\t\t\t.assertKeyType(KeetaNet.lib.Account.AccountKeyAlgorithm.TOKEN)\n\t\t\t\t.publicKeyString.get();\n\n\t\t\tconst cached = currencyMapByToken.get(tokenPub);\n\t\t\tif (cached) {\n\t\t\t\treturn(cached);\n\t\t\t}\n\n\t\t\treturn(publicKeyOrDefaultLabel(tokenPub));\n\t\t}\n\n\t\tconst s = String(convertAssetSearchInputToCanonical(asset));\n\t\treturn(s.length <= 10 ? s : `\\u2026${s.slice(-8)}`);\n\t}\n\n\tfunction esc(s: string): string {\n\t\treturn(s.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"'));\n\t}\n\n\t// Group (asset, location) entries by location string for clustering\n\tconst locationGroups = new Map<string, { asset: AnchorChainingAsset; location: AssetLocationLike }[]>();\n\tfor (const node of nodes) {\n\t\tfor (const side of [ node.from, node.to ]) {\n\t\t\tconst locStr = convertAssetLocationToString(side.location);\n\t\t\tif (!locationGroups.has(locStr)) {\n\t\t\t\tlocationGroups.set(locStr, []);\n\t\t\t}\n\t\t\tconst group = locationGroups.get(locStr);\n\t\t\tif (!group) {\n\t\t\t\tthrow(new Error(`Unexpected missing location group for location string: ${locStr}`));\n\t\t\t}\n\t\t\tconst key = assetLocationKey(side.asset, side.location);\n\t\t\tif (!group.some(g => assetLocationKey(g.asset, g.location) === key)) {\n\t\t\t\tgroup.push({ asset: side.asset, location: side.location });\n\t\t\t}\n\t\t}\n\t}\n\n\tconst lines: string[] = [\n\t\t'digraph AnchorGraph {',\n\t\t' rankdir=LR',\n\t\t' node [shape=box, style=filled, fontname=\"Helvetica\"]',\n\t\t' edge [fontsize=9, fontname=\"Helvetica\"]',\n\t\t''\n\t];\n\n\t// One cluster per location color-coded by location type\n\tlet clusterIdx = 0;\n\tfor (const [ locStr, entries ] of locationGroups) {\n\t\tconst isKeeta = locStr.startsWith('chain:keeta:');\n\t\tconst isExtChain = !isKeeta && locStr.startsWith('chain:');\n\t\t// Keeta = blue tint, fiat/bank = green tint, other external chains = red tint\n\t\tconst clusterFill = isKeeta ? '#e8f4ff' : isExtChain ? '#fff0f0' : '#f0fff0';\n\t\tconst nodeFill = isKeeta ? '#fffacd' : isExtChain ? '#ffe4e1' : '#e0ffe0';\n\n\t\tlines.push(` subgraph cluster_${clusterIdx++} {`);\n\t\tlines.push(` label=\"${esc(locStr)}\"`);\n\t\tlines.push(` style=filled`);\n\t\tlines.push(` color=\"#aaaaaa\"`);\n\t\tlines.push(` fillcolor=\"${clusterFill}\"`);\n\t\tfor (const { asset, location } of entries) {\n\t\t\tconst id = getDotId(asset, location);\n\t\t\tconst label = assetLabel(asset);\n\t\t\tconst tooltip = esc(assetLocationKey(asset, location));\n\t\t\tlines.push(` ${id} [label=\"${esc(label)}\", fillcolor=\"${nodeFill}\", tooltip=\"${tooltip}\"]`);\n\t\t}\n\t\tlines.push(' }');\n\t\tlines.push('');\n\t}\n\n\tfunction isFXLike(node: GraphNodeLike): boolean {\n\t\tif (node.type === 'fx') {\n\t\t\treturn(true);\n\t\t} else if (node.type === 'assetMovement') {\n\t\t\tif (node.from.rail === 'KEETA_SEND' && node.to.rail === 'KEETA_SEND') {\n\t\t\t\tif (convertAssetLocationToString(node.from.location) === convertAssetLocationToString(node.to.location)) {\n\t\t\t\t\treturn(true);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn(false);\n\t\t} else {\n\t\t\tassertNever(node);\n\t\t}\n\t}\n\n\tconst emittedFXLikeKeys = new Set<string>();\n\tconst emittedMoveKeys = new Set<string>();\n\n\tfor (const node of nodes) {\n\t\tconst fromKey = assetLocationKey(node.from.asset, node.from.location);\n\t\tconst toKey = assetLocationKey(node.to.asset, node.to.location);\n\t\tconst from = getDotId(node.from.asset, node.from.location);\n\t\tconst to = getDotId(node.to.asset, node.to.location);\n\n\t\tif (isFXLike(node)) {\n\t\t\tif (!input.config.showFX) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tconst [lo, hi] = fromKey < toKey ? [fromKey, toKey] : [toKey, fromKey];\n\t\t\tconst canonKey = `${lo}|${hi}|${node.providerID}`;\n\t\t\tif (emittedFXLikeKeys.has(canonKey)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\temittedFXLikeKeys.add(canonKey);\n\n\t\t\tconst hasReverse = nodes.some(n =>\n\t\t\t\tisFXLike(n) &&\n n.providerID === node.providerID &&\n assetLocationKey(n.from.asset, n.from.location) === toKey &&\n assetLocationKey(n.to.asset, n.to.location) === fromKey\n\t\t\t);\n\n\t\t\tconst edgeLabel = esc(`FX [PRV=${publicKeyOrDefaultLabel(node.providerID)}]`);\n\t\t\tconst dirAttr = hasReverse ? ', dir=both' : '';\n\t\t\tlines.push(` ${from} -> FX_${esc(publicKeyOrDefaultLabel(node.providerID))} -> ${to} [label=\"${edgeLabel}\", color=darkorange, fontcolor=darkorange, style=dashed${dirAttr}, constraint=false]`);\n\t\t} else {\n\t\t\tconst railLabel = node.to.rail;\n\n\t\t\tconst edgeLabel = esc(`${railLabel} [PRV=${publicKeyOrDefaultLabel(node.providerID)}]`);\n\t\t\tconst moveKey = `${from}|${to}|${edgeLabel}`;\n\t\t\tif (emittedMoveKeys.has(moveKey)) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\temittedMoveKeys.add(moveKey);\n\t\t\tlines.push(` ${from} -> ${to} [label=\"${edgeLabel}\", color=steelblue, fontcolor=steelblue]`);\n\t\t}\n\t}\n\n\tlines.push('}');\n\treturn(lines.join('\\n'));\n}\n\n(async () => {\n\tconst config = getConfig(process.argv.slice(2));\n\n\tconst fakeAccount = KeetaNet.lib.Account.fromSeed(KeetaNet.lib.Account.generateRandomSeed(), 0);\n\tconst userClient = KeetaNet.UserClient.fromNetwork(config.network, fakeAccount);\n\n\tconst usingRoots = config.roots;\n\tconst defaultConfig = getDefaultResolverConfig(userClient);\n\tif (!config.skipDefaultResolver) {\n\t\tusingRoots.push(...([defaultConfig.root].flat()));\n\t}\n\n\tconst resolver = new Resolver({\n\t\t...defaultConfig,\n\t\troot: usingRoots\n\t});\n\n\tconst chaining = new AnchorChaining({\n\t\tclient: userClient,\n\t\tresolver: resolver\n\t});\n\n\tconst computed = await makeGraphViz({\n\t\tgraph: chaining['graph'],\n\t\tconfig\n\t});\n\n\tconsole.log(computed);\n\n\tprocess.exit(0);\n})().catch(function(err: unknown) {\n\tconsole.error(err);\n\tprocess.exit(1);\n});\n"]}
|