@agoric/orchestration 0.1.1-calypso-dev-84eb287.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/LICENSE +201 -0
- package/README.md +5 -0
- package/index.d.ts +4 -0
- package/index.js +7 -0
- package/package.json +95 -0
- package/src/chain-info.d.ts +2318 -0
- package/src/chain-info.d.ts.map +1 -0
- package/src/chain-info.js +114 -0
- package/src/cosmos-api.d.ts +174 -0
- package/src/cosmos-api.d.ts.map +1 -0
- package/src/cosmos-api.ts +231 -0
- package/src/ethereum-api.d.ts +8 -0
- package/src/ethereum-api.d.ts.map +1 -0
- package/src/ethereum-api.ts +7 -0
- package/src/examples/sendAnywhere.contract.d.ts +31 -0
- package/src/examples/sendAnywhere.contract.d.ts.map +1 -0
- package/src/examples/sendAnywhere.contract.js +171 -0
- package/src/examples/stakeBld.contract.d.ts +121 -0
- package/src/examples/stakeBld.contract.d.ts.map +1 -0
- package/src/examples/stakeBld.contract.js +133 -0
- package/src/examples/stakeIca.contract.d.ts +93 -0
- package/src/examples/stakeIca.contract.d.ts.map +1 -0
- package/src/examples/stakeIca.contract.js +143 -0
- package/src/examples/swapExample.contract.d.ts +34 -0
- package/src/examples/swapExample.contract.d.ts.map +1 -0
- package/src/examples/swapExample.contract.js +155 -0
- package/src/examples/unbondExample.contract.d.ts +21 -0
- package/src/examples/unbondExample.contract.d.ts.map +1 -0
- package/src/examples/unbondExample.contract.js +105 -0
- package/src/exos/README.md +56 -0
- package/src/exos/agoric-names-tools.d.ts +27 -0
- package/src/exos/agoric-names-tools.d.ts.map +1 -0
- package/src/exos/agoric-names-tools.js +109 -0
- package/src/exos/chain-account-kit.d.ts +88 -0
- package/src/exos/chain-account-kit.d.ts.map +1 -0
- package/src/exos/chain-account-kit.js +210 -0
- package/src/exos/chain-hub.d.ts +77 -0
- package/src/exos/chain-hub.d.ts.map +1 -0
- package/src/exos/chain-hub.js +214 -0
- package/src/exos/cosmos-orchestration-account.d.ts +207 -0
- package/src/exos/cosmos-orchestration-account.d.ts.map +1 -0
- package/src/exos/cosmos-orchestration-account.js +536 -0
- package/src/exos/icq-connection-kit.d.ts +50 -0
- package/src/exos/icq-connection-kit.d.ts.map +1 -0
- package/src/exos/icq-connection-kit.js +135 -0
- package/src/exos/local-chain-facade.d.ts +81 -0
- package/src/exos/local-chain-facade.d.ts.map +1 -0
- package/src/exos/local-chain-facade.js +113 -0
- package/src/exos/local-orchestration-account.d.ts +176 -0
- package/src/exos/local-orchestration-account.d.ts.map +1 -0
- package/src/exos/local-orchestration-account.js +446 -0
- package/src/exos/orchestrator.d.ts +91 -0
- package/src/exos/orchestrator.d.ts.map +1 -0
- package/src/exos/orchestrator.js +141 -0
- package/src/exos/remote-chain-facade.d.ts +144 -0
- package/src/exos/remote-chain-facade.d.ts.map +1 -0
- package/src/exos/remote-chain-facade.js +145 -0
- package/src/facade.d.ts +57 -0
- package/src/facade.d.ts.map +1 -0
- package/src/facade.js +132 -0
- package/src/fetched-chain-info.d.ts +2311 -0
- package/src/fetched-chain-info.d.ts.map +1 -0
- package/src/fetched-chain-info.js +2288 -0
- package/src/internal.d.ts +13 -0
- package/src/internal.d.ts.map +1 -0
- package/src/internal.ts +20 -0
- package/src/orchestration-api.d.ts +158 -0
- package/src/orchestration-api.d.ts.map +1 -0
- package/src/orchestration-api.ts +201 -0
- package/src/proposals/orchestration-proposal.d.ts +53 -0
- package/src/proposals/orchestration-proposal.d.ts.map +1 -0
- package/src/proposals/orchestration-proposal.js +179 -0
- package/src/proposals/revise-chain-info.d.ts +21 -0
- package/src/proposals/revise-chain-info.d.ts.map +1 -0
- package/src/proposals/revise-chain-info.js +44 -0
- package/src/proposals/start-stakeAtom.d.ts +109 -0
- package/src/proposals/start-stakeAtom.d.ts.map +1 -0
- package/src/proposals/start-stakeAtom.js +105 -0
- package/src/proposals/start-stakeBld.d.ts +154 -0
- package/src/proposals/start-stakeBld.d.ts.map +1 -0
- package/src/proposals/start-stakeBld.js +103 -0
- package/src/proposals/start-stakeOsmo.d.ts +108 -0
- package/src/proposals/start-stakeOsmo.d.ts.map +1 -0
- package/src/proposals/start-stakeOsmo.js +106 -0
- package/src/service.d.ts +97 -0
- package/src/service.d.ts.map +1 -0
- package/src/service.js +259 -0
- package/src/typeGuards.d.ts +55 -0
- package/src/typeGuards.d.ts.map +1 -0
- package/src/typeGuards.js +104 -0
- package/src/types.d.ts +11 -0
- package/src/types.d.ts.map +1 -0
- package/src/types.ts +11 -0
- package/src/utils/address.d.ts +14 -0
- package/src/utils/address.d.ts.map +1 -0
- package/src/utils/address.js +79 -0
- package/src/utils/cosmos.d.ts +9 -0
- package/src/utils/cosmos.d.ts.map +1 -0
- package/src/utils/cosmos.js +36 -0
- package/src/utils/orc.d.ts +17 -0
- package/src/utils/orc.d.ts.map +1 -0
- package/src/utils/orc.js +38 -0
- package/src/utils/orchestrationAccount.d.ts +10 -0
- package/src/utils/orchestrationAccount.d.ts.map +1 -0
- package/src/utils/orchestrationAccount.js +22 -0
- package/src/utils/packet.d.ts +57 -0
- package/src/utils/packet.d.ts.map +1 -0
- package/src/utils/packet.js +112 -0
- package/src/utils/registry.d.ts +13 -0
- package/src/utils/registry.d.ts.map +1 -0
- package/src/utils/registry.js +131 -0
- package/src/utils/start-helper.d.ts +51 -0
- package/src/utils/start-helper.d.ts.map +1 -0
- package/src/utils/start-helper.js +109 -0
- package/src/utils/time.d.ts +31 -0
- package/src/utils/time.d.ts.map +1 -0
- package/src/utils/time.js +63 -0
- package/src/vat-orchestration.d.ts +58 -0
- package/src/vat-orchestration.d.ts.map +1 -0
- package/src/vat-orchestration.js +24 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { Fail } from '@agoric/assert';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @import {IBCConnectionID} from '@agoric/vats';
|
|
5
|
+
* @import {ChainAddress} from '../types.js';
|
|
6
|
+
* @import {RemoteIbcAddress} from '@agoric/vats/tools/ibc-utils.js';
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @param {IBCConnectionID} hostConnectionId Counterpart Connection ID
|
|
11
|
+
* @param {IBCConnectionID} controllerConnectionId Self Connection ID
|
|
12
|
+
* @param {object} [opts]
|
|
13
|
+
* @param {string} [opts.encoding] - message encoding format for the channel.
|
|
14
|
+
* default is `proto3`
|
|
15
|
+
* @param {'ordered' | 'unordered'} [opts.ordering] - channel ordering.
|
|
16
|
+
* currently only `ordered` is supported for ics27-1
|
|
17
|
+
* @param {string} [opts.txType] - default is `sdk_multi_msg`
|
|
18
|
+
* @param {string} [opts.version] - default is `ics27-1`
|
|
19
|
+
* @returns {RemoteIbcAddress}
|
|
20
|
+
*/
|
|
21
|
+
export const makeICAChannelAddress = (
|
|
22
|
+
hostConnectionId,
|
|
23
|
+
controllerConnectionId,
|
|
24
|
+
{
|
|
25
|
+
version = 'ics27-1',
|
|
26
|
+
encoding = 'proto3',
|
|
27
|
+
ordering = 'ordered',
|
|
28
|
+
txType = 'sdk_multi_msg',
|
|
29
|
+
} = {},
|
|
30
|
+
) => {
|
|
31
|
+
hostConnectionId || Fail`hostConnectionId is required`;
|
|
32
|
+
controllerConnectionId || Fail`controllerConnectionId is required`;
|
|
33
|
+
const connString = JSON.stringify({
|
|
34
|
+
version,
|
|
35
|
+
controllerConnectionId,
|
|
36
|
+
hostConnectionId,
|
|
37
|
+
address: '', // will be provided by the counterparty after channelOpenAck
|
|
38
|
+
encoding,
|
|
39
|
+
txType,
|
|
40
|
+
});
|
|
41
|
+
return `/ibc-hop/${controllerConnectionId}/ibc-port/icahost/${ordering}/${connString}`;
|
|
42
|
+
};
|
|
43
|
+
harden(makeICAChannelAddress);
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* @param {IBCConnectionID} controllerConnectionId
|
|
47
|
+
* @param {{ version?: string }} [opts]
|
|
48
|
+
* @returns {RemoteIbcAddress}
|
|
49
|
+
*/
|
|
50
|
+
export const makeICQChannelAddress = (
|
|
51
|
+
controllerConnectionId,
|
|
52
|
+
{ version = 'icq-1' } = {},
|
|
53
|
+
) => {
|
|
54
|
+
controllerConnectionId || Fail`controllerConnectionId is required`;
|
|
55
|
+
return `/ibc-hop/${controllerConnectionId}/ibc-port/icqhost/unordered/${version}`;
|
|
56
|
+
};
|
|
57
|
+
harden(makeICQChannelAddress);
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Parse a chain address from a remote address string. Assumes the address
|
|
61
|
+
* string is in a JSON format and contains an "address" field. This function is
|
|
62
|
+
* designed to be safe against malformed inputs and unexpected data types, and
|
|
63
|
+
* will return `undefined` in those cases.
|
|
64
|
+
*
|
|
65
|
+
* @param {RemoteIbcAddress} remoteAddressString - remote address string,
|
|
66
|
+
* including version
|
|
67
|
+
* @returns {ChainAddress['address'] | undefined} returns undefined on error
|
|
68
|
+
*/
|
|
69
|
+
export const findAddressField = remoteAddressString => {
|
|
70
|
+
try {
|
|
71
|
+
// Extract JSON version string assuming it's always surrounded by {}
|
|
72
|
+
const jsonStr = remoteAddressString?.match(/{.*?}/)?.[0];
|
|
73
|
+
const jsonObj = jsonStr ? JSON.parse(jsonStr) : undefined;
|
|
74
|
+
return jsonObj?.address ?? undefined;
|
|
75
|
+
} catch (error) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
harden(findAddressField);
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** maximum clock skew, in seconds, for unbonding time reported from other chain */
|
|
2
|
+
export const maxClockSkew: bigint;
|
|
3
|
+
export function encodeTxResponse(response: unknown, toProtoMsg: (msg: any) => Any): string;
|
|
4
|
+
export function tryDecodeResponse<T>(ackStr: string, fromProtoMsg: (p: {
|
|
5
|
+
typeUrl: string;
|
|
6
|
+
value: Uint8Array;
|
|
7
|
+
}) => T): T;
|
|
8
|
+
import { Any } from '@agoric/cosmic-proto/google/protobuf/any.js';
|
|
9
|
+
//# sourceMappingURL=cosmos.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cosmos.d.ts","sourceRoot":"","sources":["cosmos.js"],"names":[],"mappings":"AAIA,mFAAmF;AACnF,kCAAsC;AAO/B,2CAJI,OAAO,cACP,CAAC,GAAG,EAAE,GAAG,KAAK,GAAG,GACf,MAAM,CAQlB;AAOM,kCAJM,CAAC,UACH,MAAM,gBACN,CAAC,CAAC,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,KAAK,CAAC,KAY1D;oBAlCmB,6CAA6C"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { assert } from '@agoric/assert';
|
|
2
|
+
import { Any } from '@agoric/cosmic-proto/google/protobuf/any.js';
|
|
3
|
+
import { decodeBase64, encodeBase64 } from '@endo/base64';
|
|
4
|
+
|
|
5
|
+
/** maximum clock skew, in seconds, for unbonding time reported from other chain */
|
|
6
|
+
export const maxClockSkew = 10n * 60n;
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @param {unknown} response
|
|
10
|
+
* @param {(msg: any) => Any} toProtoMsg
|
|
11
|
+
* @returns {string}
|
|
12
|
+
*/
|
|
13
|
+
export const encodeTxResponse = (response, toProtoMsg) => {
|
|
14
|
+
const protoMsg = toProtoMsg(response);
|
|
15
|
+
const any1 = Any.fromPartial(protoMsg);
|
|
16
|
+
const any2 = Any.fromPartial({ value: Any.encode(any1).finish() });
|
|
17
|
+
const ackStr = encodeBase64(Any.encode(any2).finish());
|
|
18
|
+
return ackStr;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @template T
|
|
23
|
+
* @param {string} ackStr
|
|
24
|
+
* @param {(p: { typeUrl: string; value: Uint8Array }) => T} fromProtoMsg
|
|
25
|
+
*/
|
|
26
|
+
export const tryDecodeResponse = (ackStr, fromProtoMsg) => {
|
|
27
|
+
try {
|
|
28
|
+
const any = Any.decode(decodeBase64(ackStr));
|
|
29
|
+
const protoMsg = Any.decode(any.value);
|
|
30
|
+
|
|
31
|
+
const msg = fromProtoMsg(protoMsg);
|
|
32
|
+
return msg;
|
|
33
|
+
} catch (cause) {
|
|
34
|
+
throw assert.error(`bad response: ${ackStr}`, undefined, { cause });
|
|
35
|
+
}
|
|
36
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export namespace orcUtils {
|
|
2
|
+
function makeTransferMsg(_args: Omit<TransferMsg, "memo">): TransferMsg;
|
|
3
|
+
/**
|
|
4
|
+
* SwapExact or SwapMaxSlippage, with optional AfterAction
|
|
5
|
+
*
|
|
6
|
+
* @param {(SwapExact | SwapMaxSlippage) &
|
|
7
|
+
* (AfterAction | Record<string, never>)} _args
|
|
8
|
+
*
|
|
9
|
+
* @returns {TransferMsg}
|
|
10
|
+
*/
|
|
11
|
+
function makeOsmosisSwap(_args: (SwapExact | SwapMaxSlippage) & (AfterAction | Record<string, never>)): TransferMsg;
|
|
12
|
+
}
|
|
13
|
+
import type { TransferMsg } from '../types.js';
|
|
14
|
+
import type { SwapExact } from '../types.js';
|
|
15
|
+
import type { SwapMaxSlippage } from '../types.js';
|
|
16
|
+
import type { AfterAction } from '../types.js';
|
|
17
|
+
//# sourceMappingURL=orc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orc.d.ts","sourceRoot":"","sources":["orc.js"],"names":[],"mappings":";IASmB,gCAHN,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,GACvB,WAAW,CAWvB;IACD;;;;;;;OAOG;IACH,gCALW,CAAC,SAAS,GAAG,eAAe,CAAC,GACvC,CAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,GAE7B,WAAW,CAWvB;;iCApCqE,aAAa;+BAAb,aAAa;qCAAb,aAAa;iCAAb,aAAa"}
|
package/src/utils/orc.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/** @import {AfterAction, SwapExact, SwapMaxSlippage, TransferMsg} from '../types.js' */
|
|
2
|
+
|
|
3
|
+
export const orcUtils = {
|
|
4
|
+
/**
|
|
5
|
+
* unwinds denom with PFM, if necessary
|
|
6
|
+
*
|
|
7
|
+
* @param {Omit<TransferMsg, 'memo'>} _args
|
|
8
|
+
* @returns {TransferMsg}
|
|
9
|
+
*/
|
|
10
|
+
makeTransferMsg: _args => {
|
|
11
|
+
// FIXME mocked, so typescript is happy
|
|
12
|
+
return {
|
|
13
|
+
toAccount: {
|
|
14
|
+
chainId: 'osmosis-test',
|
|
15
|
+
address: 'osmo1234',
|
|
16
|
+
addressEncoding: 'bech32',
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
},
|
|
20
|
+
/**
|
|
21
|
+
* SwapExact or SwapMaxSlippage, with optional AfterAction
|
|
22
|
+
*
|
|
23
|
+
* @param {(SwapExact | SwapMaxSlippage) &
|
|
24
|
+
* (AfterAction | Record<string, never>)} _args
|
|
25
|
+
*
|
|
26
|
+
* @returns {TransferMsg}
|
|
27
|
+
*/
|
|
28
|
+
makeOsmosisSwap(_args) {
|
|
29
|
+
// FIXME mocked, so typescript is happy
|
|
30
|
+
return {
|
|
31
|
+
toAccount: {
|
|
32
|
+
chainId: 'osmosis-test',
|
|
33
|
+
address: 'osmo1234',
|
|
34
|
+
addressEncoding: 'bech32',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
},
|
|
38
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export namespace orchestrationAccountMethods {
|
|
2
|
+
let getAddress: import("@endo/patterns").MethodGuard;
|
|
3
|
+
let getBalance: import("@endo/patterns").MethodGuard;
|
|
4
|
+
let getBalances: import("@endo/patterns").MethodGuard;
|
|
5
|
+
let send: import("@endo/patterns").MethodGuard;
|
|
6
|
+
let transfer: import("@endo/patterns").MethodGuard;
|
|
7
|
+
let transferSteps: import("@endo/patterns").MethodGuard;
|
|
8
|
+
let deposit: import("@endo/patterns").MethodGuard;
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=orchestrationAccount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrationAccount.d.ts","sourceRoot":"","sources":["orchestrationAccount.js"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { M } from '@endo/patterns';
|
|
2
|
+
import { PaymentShape } from '@agoric/ertp';
|
|
3
|
+
import { Shape as NetworkShape } from '@agoric/network';
|
|
4
|
+
import { VowShape } from '@agoric/vow';
|
|
5
|
+
import { AmountArgShape, ChainAddressShape, CoinShape } from '../typeGuards.js';
|
|
6
|
+
|
|
7
|
+
/** @import {OrchestrationAccountI} from '../orchestration-api.js'; */
|
|
8
|
+
|
|
9
|
+
const { Vow$ } = NetworkShape; // TODO #9611
|
|
10
|
+
|
|
11
|
+
/** @see {OrchestrationAccountI} */
|
|
12
|
+
export const orchestrationAccountMethods = {
|
|
13
|
+
getAddress: M.call().returns(ChainAddressShape),
|
|
14
|
+
getBalance: M.call(M.any()).returns(Vow$(CoinShape)),
|
|
15
|
+
getBalances: M.call().returns(Vow$(M.arrayOf(CoinShape))),
|
|
16
|
+
send: M.call(ChainAddressShape, AmountArgShape).returns(VowShape),
|
|
17
|
+
transfer: M.call(AmountArgShape, ChainAddressShape)
|
|
18
|
+
.optional(M.record())
|
|
19
|
+
.returns(VowShape),
|
|
20
|
+
transferSteps: M.call(AmountArgShape, M.any()).returns(VowShape),
|
|
21
|
+
deposit: M.call(PaymentShape).returns(VowShape),
|
|
22
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @import {AnyJson, JsonSafe} from '@agoric/cosmic-proto';
|
|
3
|
+
* @import {InterchainAccountPacketData} from '@agoric/cosmic-proto/ibc/applications/interchain_accounts/v1/packet.js';
|
|
4
|
+
* @import {InterchainQueryPacketData} from '@agoric/cosmic-proto/icq/v1/packet.js';
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Makes an IBC transaction packet from an array of messages. Expects the
|
|
8
|
+
* `value` of each message to be base64 encoded bytes. Skips checks for
|
|
9
|
+
* malformed messages in favor of interface guards.
|
|
10
|
+
*
|
|
11
|
+
* @param {AnyJson[]} msgs
|
|
12
|
+
* @param {Partial<Omit<TxBody, 'messages'>>} [opts]
|
|
13
|
+
* @returns {string} stringified InterchainAccountPacketData
|
|
14
|
+
* @throws {Error} if malformed messages are provided
|
|
15
|
+
*/
|
|
16
|
+
export function makeTxPacket(msgs: AnyJson[], opts?: Partial<Omit<TxBody, "messages">> | undefined): string;
|
|
17
|
+
/**
|
|
18
|
+
* Makes an IBC query packet from an array of query messages. Expects the `data`
|
|
19
|
+
* of each message to be base64 encoded bytes. Skips checks for malformed
|
|
20
|
+
* messages in favor of interface guards.
|
|
21
|
+
*
|
|
22
|
+
* @param {JsonSafe<RequestQuery>[]} msgs
|
|
23
|
+
* @returns {string} stringified InterchainQueryPacketData
|
|
24
|
+
* @throws {Error} if malformed messages are provided
|
|
25
|
+
*/
|
|
26
|
+
export function makeQueryPacket(msgs: JsonSafe<RequestQuery>[]): string;
|
|
27
|
+
/**
|
|
28
|
+
* Looks for a result or error key in the response string, and returns a
|
|
29
|
+
* Base64Bytes string. This string can be decoded using the corresponding
|
|
30
|
+
* Msg*Response object. Error strings seem to be plain text and do not need
|
|
31
|
+
* decoding.
|
|
32
|
+
*
|
|
33
|
+
* @param {string} response
|
|
34
|
+
* @returns {string} - base64 encoded bytes string
|
|
35
|
+
* @throws {Error} if error key is detected in response string, or result key is
|
|
36
|
+
* not found
|
|
37
|
+
*/
|
|
38
|
+
export function parseTxPacket(response: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Looks for a result or error key in the response string. If a result is found,
|
|
41
|
+
* `responses` is decoded via `CosmosResponse`. The `key` and `value` fields on
|
|
42
|
+
* the resulting entries are base64 encoded for inter-vat communication. These
|
|
43
|
+
* can be decoded using the corresponding Query*Response objects. Error strings
|
|
44
|
+
* seem to be plain text and do not need decoding.
|
|
45
|
+
*
|
|
46
|
+
* @param {string} response
|
|
47
|
+
* @returns {JsonSafe<ResponseQuery>[]}
|
|
48
|
+
* @throws {Error} if error key is detected in response string, or result key is
|
|
49
|
+
* not found
|
|
50
|
+
*/
|
|
51
|
+
export function parseQueryPacket(response: string): JsonSafe<ResponseQuery>[];
|
|
52
|
+
import type { AnyJson } from '@agoric/cosmic-proto';
|
|
53
|
+
import { TxBody } from '@agoric/cosmic-proto/cosmos/tx/v1beta1/tx.js';
|
|
54
|
+
import { RequestQuery } from '@agoric/cosmic-proto/tendermint/abci/types.js';
|
|
55
|
+
import type { JsonSafe } from '@agoric/cosmic-proto';
|
|
56
|
+
import { ResponseQuery } from '@agoric/cosmic-proto/tendermint/abci/types.js';
|
|
57
|
+
//# sourceMappingURL=packet.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"packet.d.ts","sourceRoot":"","sources":["packet.js"],"names":[],"mappings":"AAcA;;;;GAIG;AAEH;;;;;;;;;GASG;AACH,mCALW,OAAO,EAAE,yDAEP,MAAM,CAmBlB;AAGD;;;;;;;;GAQG;AACH,sCAJW,SAAS,YAAY,CAAC,EAAE,GACtB,MAAM,CAgBlB;AAGD;;;;;;;;;;GAUG;AACH,wCALW,MAAM,GACJ,MAAM,CASlB;AAGD;;;;;;;;;;;GAWG;AACH,2CALW,MAAM,GACJ,SAAS,aAAa,CAAC,EAAE,CASrC;6BA/FmC,sBAAsB;uBAdnC,8CAA8C;6BAK9D,+CAA+C;8BASlB,sBAAsB;8BATnD,+CAA+C"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Fail } from '@endo/errors';
|
|
2
|
+
import { TxBody } from '@agoric/cosmic-proto/cosmos/tx/v1beta1/tx.js';
|
|
3
|
+
import { Any } from '@agoric/cosmic-proto/google/protobuf/any.js';
|
|
4
|
+
import {
|
|
5
|
+
RequestQuery,
|
|
6
|
+
ResponseQuery,
|
|
7
|
+
} from '@agoric/cosmic-proto/tendermint/abci/types.js';
|
|
8
|
+
import { atob, decodeBase64, encodeBase64 } from '@endo/base64';
|
|
9
|
+
import {
|
|
10
|
+
CosmosQuery,
|
|
11
|
+
CosmosResponse,
|
|
12
|
+
} from '@agoric/cosmic-proto/icq/v1/packet.js';
|
|
13
|
+
import { Type as PacketType } from '@agoric/cosmic-proto/ibc/applications/interchain_accounts/v1/packet.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @import {AnyJson, JsonSafe} from '@agoric/cosmic-proto';
|
|
17
|
+
* @import {InterchainAccountPacketData} from '@agoric/cosmic-proto/ibc/applications/interchain_accounts/v1/packet.js';
|
|
18
|
+
* @import {InterchainQueryPacketData} from '@agoric/cosmic-proto/icq/v1/packet.js';
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Makes an IBC transaction packet from an array of messages. Expects the
|
|
23
|
+
* `value` of each message to be base64 encoded bytes. Skips checks for
|
|
24
|
+
* malformed messages in favor of interface guards.
|
|
25
|
+
*
|
|
26
|
+
* @param {AnyJson[]} msgs
|
|
27
|
+
* @param {Partial<Omit<TxBody, 'messages'>>} [opts]
|
|
28
|
+
* @returns {string} stringified InterchainAccountPacketData
|
|
29
|
+
* @throws {Error} if malformed messages are provided
|
|
30
|
+
*/
|
|
31
|
+
export function makeTxPacket(msgs, opts) {
|
|
32
|
+
const messages = msgs.map(Any.fromJSON);
|
|
33
|
+
const bytes = TxBody.encode(
|
|
34
|
+
TxBody.fromPartial({
|
|
35
|
+
messages,
|
|
36
|
+
...opts,
|
|
37
|
+
}),
|
|
38
|
+
).finish();
|
|
39
|
+
|
|
40
|
+
return JSON.stringify(
|
|
41
|
+
/** @type {JsonSafe<InterchainAccountPacketData>} */ ({
|
|
42
|
+
type: PacketType.TYPE_EXECUTE_TX,
|
|
43
|
+
data: encodeBase64(bytes),
|
|
44
|
+
memo: '',
|
|
45
|
+
}),
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
harden(makeTxPacket);
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Makes an IBC query packet from an array of query messages. Expects the `data`
|
|
52
|
+
* of each message to be base64 encoded bytes. Skips checks for malformed
|
|
53
|
+
* messages in favor of interface guards.
|
|
54
|
+
*
|
|
55
|
+
* @param {JsonSafe<RequestQuery>[]} msgs
|
|
56
|
+
* @returns {string} stringified InterchainQueryPacketData
|
|
57
|
+
* @throws {Error} if malformed messages are provided
|
|
58
|
+
*/
|
|
59
|
+
export function makeQueryPacket(msgs) {
|
|
60
|
+
const bytes = CosmosQuery.encode(
|
|
61
|
+
CosmosQuery.fromPartial({
|
|
62
|
+
requests: msgs.map(RequestQuery.fromJSON),
|
|
63
|
+
}),
|
|
64
|
+
).finish();
|
|
65
|
+
|
|
66
|
+
return JSON.stringify(
|
|
67
|
+
/** @type {JsonSafe<InterchainQueryPacketData>} */ ({
|
|
68
|
+
data: encodeBase64(bytes),
|
|
69
|
+
memo: '',
|
|
70
|
+
}),
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
harden(makeQueryPacket);
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Looks for a result or error key in the response string, and returns a
|
|
77
|
+
* Base64Bytes string. This string can be decoded using the corresponding
|
|
78
|
+
* Msg*Response object. Error strings seem to be plain text and do not need
|
|
79
|
+
* decoding.
|
|
80
|
+
*
|
|
81
|
+
* @param {string} response
|
|
82
|
+
* @returns {string} - base64 encoded bytes string
|
|
83
|
+
* @throws {Error} if error key is detected in response string, or result key is
|
|
84
|
+
* not found
|
|
85
|
+
*/
|
|
86
|
+
export function parseTxPacket(response) {
|
|
87
|
+
const { result, error } = JSON.parse(response);
|
|
88
|
+
if (result) return result;
|
|
89
|
+
else if (error) throw Error(error);
|
|
90
|
+
else throw Fail`expected either result or error: ${response}`;
|
|
91
|
+
}
|
|
92
|
+
harden(parseTxPacket);
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Looks for a result or error key in the response string. If a result is found,
|
|
96
|
+
* `responses` is decoded via `CosmosResponse`. The `key` and `value` fields on
|
|
97
|
+
* the resulting entries are base64 encoded for inter-vat communication. These
|
|
98
|
+
* can be decoded using the corresponding Query*Response objects. Error strings
|
|
99
|
+
* seem to be plain text and do not need decoding.
|
|
100
|
+
*
|
|
101
|
+
* @param {string} response
|
|
102
|
+
* @returns {JsonSafe<ResponseQuery>[]}
|
|
103
|
+
* @throws {Error} if error key is detected in response string, or result key is
|
|
104
|
+
* not found
|
|
105
|
+
*/
|
|
106
|
+
export function parseQueryPacket(response) {
|
|
107
|
+
const result = parseTxPacket(response);
|
|
108
|
+
const { data } = JSON.parse(atob(result));
|
|
109
|
+
const { responses = [] } = CosmosResponse.decode(decodeBase64(data));
|
|
110
|
+
return harden(responses.map(ResponseQuery.toJSON));
|
|
111
|
+
}
|
|
112
|
+
harden(parseQueryPacket);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export function convertChainInfo(registry: Pick<ChainRegistryClient, "chains" | "ibcData">): Promise<{
|
|
2
|
+
[k: string]: Readonly<{
|
|
3
|
+
chainId: string;
|
|
4
|
+
connections?: Record<string, IBCConnectionInfo>;
|
|
5
|
+
icqEnabled?: boolean;
|
|
6
|
+
stakingTokens?: Readonly<Array<{
|
|
7
|
+
denom: string;
|
|
8
|
+
}>>;
|
|
9
|
+
}>;
|
|
10
|
+
}>;
|
|
11
|
+
import type { ChainRegistryClient } from '@chain-registry/client';
|
|
12
|
+
import type { IBCConnectionInfo } from '../cosmos-api.js';
|
|
13
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["registry.js"],"names":[],"mappings":"AAwFO,2CAFI,IAAI,CAAC,mBAAmB,EAAE,QAAQ,GAAG,SAAS,CAAC;;;;;;;;;GA4CzD;yCAxHqC,wBAAwB;uCACT,kBAAkB"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import {
|
|
2
|
+
State as IBCChannelState,
|
|
3
|
+
Order,
|
|
4
|
+
} from '@agoric/cosmic-proto/ibc/core/channel/v1/channel.js';
|
|
5
|
+
import { State as IBCConnectionState } from '@agoric/cosmic-proto/ibc/core/connection/v1/connection.js';
|
|
6
|
+
import assert from 'node:assert';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @import {IBCChannelID, IBCConnectionID} from '@agoric/vats';
|
|
10
|
+
* @import {Chain, IBCInfo} from '@chain-registry/types';
|
|
11
|
+
* @import {ChainRegistryClient} from '@chain-registry/client';
|
|
12
|
+
* @import {CosmosChainInfo, IBCConnectionInfo} from '../cosmos-api.js';
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* @param {IBCInfo} ibcInfo
|
|
17
|
+
* @param {string} name
|
|
18
|
+
* @param {Record<string, CosmosChainInfo>} chainInfo
|
|
19
|
+
* @returns {[string, IBCConnectionInfo] | []}
|
|
20
|
+
*/
|
|
21
|
+
function toConnectionEntry(ibcInfo, name, chainInfo) {
|
|
22
|
+
// IbcInfo encodes the undirected edge as a tuple of (chain_1, chain_2) in alphabetical order
|
|
23
|
+
const fromChain1 = ibcInfo.chain_1.chain_name === name;
|
|
24
|
+
const [from, to] = fromChain1
|
|
25
|
+
? [ibcInfo.chain_1, ibcInfo.chain_2]
|
|
26
|
+
: [ibcInfo.chain_2, ibcInfo.chain_1];
|
|
27
|
+
assert.equal(from.chain_name, name);
|
|
28
|
+
const transferChannels = ibcInfo.channels.filter(
|
|
29
|
+
c =>
|
|
30
|
+
c.chain_1.port_id === 'transfer' &&
|
|
31
|
+
// @ts-expect-error tags does not specify keys
|
|
32
|
+
c.tags?.preferred,
|
|
33
|
+
);
|
|
34
|
+
if (transferChannels.length === 0) {
|
|
35
|
+
console.warn(
|
|
36
|
+
'no transfer channel for [',
|
|
37
|
+
from.chain_name,
|
|
38
|
+
to.chain_name,
|
|
39
|
+
']',
|
|
40
|
+
'(skipping)',
|
|
41
|
+
);
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
if (transferChannels.length > 1) {
|
|
45
|
+
console.warn(
|
|
46
|
+
'multiple preferred transfer channels [',
|
|
47
|
+
from.chain_name,
|
|
48
|
+
to.chain_name,
|
|
49
|
+
']:',
|
|
50
|
+
transferChannels,
|
|
51
|
+
'(choosing first)',
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
const [channel] = transferChannels;
|
|
55
|
+
const [channelFrom, channelTo] = fromChain1
|
|
56
|
+
? [channel.chain_2, channel.chain_1]
|
|
57
|
+
: [channel.chain_1, channel.chain_2];
|
|
58
|
+
const record = {
|
|
59
|
+
id: /** @type {IBCConnectionID} */ (from.connection_id),
|
|
60
|
+
client_id: from.client_id,
|
|
61
|
+
counterparty: {
|
|
62
|
+
client_id: to.client_id,
|
|
63
|
+
connection_id: /** @type {IBCConnectionID} */ (to.connection_id),
|
|
64
|
+
prefix: {
|
|
65
|
+
key_prefix: 'FIXME',
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
state: IBCConnectionState.STATE_OPEN, // XXX presumably
|
|
69
|
+
transferChannel: {
|
|
70
|
+
channelId: /** @type {IBCChannelID} */ (channelFrom.channel_id),
|
|
71
|
+
portId: channelFrom.port_id,
|
|
72
|
+
counterPartyChannelId: /** @type {IBCChannelID} */ (channelTo.channel_id),
|
|
73
|
+
counterPartyPortId: channelTo.port_id,
|
|
74
|
+
// FIXME mapping, our guard expects a numerical enum
|
|
75
|
+
ordering: Order.ORDER_NONE_UNSPECIFIED,
|
|
76
|
+
state: IBCChannelState.STATE_OPEN, // XXX presumably
|
|
77
|
+
version: channel.version,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
const destChainId = chainInfo[to.chain_name].chainId;
|
|
81
|
+
return [destChainId, record];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Converts the given chain info to our local config format
|
|
86
|
+
*
|
|
87
|
+
* @param {Pick<ChainRegistryClient, 'chains' | 'ibcData'>} registry
|
|
88
|
+
*/
|
|
89
|
+
export const convertChainInfo = async registry => {
|
|
90
|
+
/** @type {Record<string, CosmosChainInfo>} */
|
|
91
|
+
const chainInfo = {};
|
|
92
|
+
|
|
93
|
+
for (const chain of registry.chains) {
|
|
94
|
+
console.log('processing info', chain.chain_name);
|
|
95
|
+
chainInfo[chain.chain_name] = {
|
|
96
|
+
chainId: chain.chain_id,
|
|
97
|
+
stakingTokens: chain.staking?.staking_tokens,
|
|
98
|
+
// UNTIL https://github.com/Agoric/agoric-sdk/issues/9326
|
|
99
|
+
icqEnabled: chain.chain_name === 'osmosis',
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// XXX probably easier to keep ibc separate
|
|
104
|
+
const ibcLookup = {};
|
|
105
|
+
for (const ibc of registry.ibcData) {
|
|
106
|
+
ibcLookup[ibc.chain_1.chain_name] ||= [];
|
|
107
|
+
ibcLookup[ibc.chain_2.chain_name] ||= [];
|
|
108
|
+
|
|
109
|
+
ibcLookup[ibc.chain_1.chain_name].push(ibc);
|
|
110
|
+
ibcLookup[ibc.chain_2.chain_name].push(ibc);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const chainNames = registry.chains.map(c => c.chain_name).sort();
|
|
114
|
+
|
|
115
|
+
// iterate this after chainInfo is filled out
|
|
116
|
+
for (const name of chainNames) {
|
|
117
|
+
console.log('processing connections', name);
|
|
118
|
+
|
|
119
|
+
const ibcData = ibcLookup[name];
|
|
120
|
+
const connections = Object.fromEntries(
|
|
121
|
+
ibcData
|
|
122
|
+
.map(datum => toConnectionEntry(datum, name, chainInfo))
|
|
123
|
+
// sort alphabetically for consistency
|
|
124
|
+
.sort(([a], [b]) => (a && b ? a.localeCompare(b) : 0)),
|
|
125
|
+
);
|
|
126
|
+
chainInfo[name] = { ...chainInfo[name], connections };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// return object with insertion in alphabetical order of chain name
|
|
130
|
+
return Object.fromEntries(chainNames.map(name => [name, chainInfo[name]]));
|
|
131
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export function provideOrchestration(zcf: ZCF, baggage: Baggage, remotePowers: OrchestrationPowers, marshaller: Marshaller): {
|
|
2
|
+
chainHub: import("@endo/exo").Guarded<{
|
|
3
|
+
registerChain(name: string, chainInfo: import("../cosmos-api.js").CosmosChainInfo): void;
|
|
4
|
+
getChainInfo<K extends string>(chainName: K): import("@agoric/vow").Vow<ActualChainInfo<K>>;
|
|
5
|
+
registerConnection(chainId1: string, chainId2: string, connectionInfo: import("../cosmos-api.js").IBCConnectionInfo): void;
|
|
6
|
+
getConnectionInfo(chain1: string | {
|
|
7
|
+
chainId: string;
|
|
8
|
+
}, chain2: string | {
|
|
9
|
+
chainId: string;
|
|
10
|
+
}): import("@agoric/vow").Vow<import("../cosmos-api.js").IBCConnectionInfo>;
|
|
11
|
+
getChainsAndConnection<C1 extends string, C2 extends string>(chainName1: C1, chainName2: C2): import("@agoric/vow").Vow<[ActualChainInfo<C1>, ActualChainInfo<C2>, import("../cosmos-api.js").IBCConnectionInfo]>;
|
|
12
|
+
}>;
|
|
13
|
+
vowTools: {
|
|
14
|
+
E: (<T>(x: T, opts?: import("@agoric/vow").EUnwrapOptions | undefined) => ECallableOrMethods<RemoteFunctions<T>>) & {
|
|
15
|
+
readonly get: <T>(x: T, opts?: import("@agoric/vow").EUnwrapOptions | undefined) => EGetters<LocalRecord<T>>;
|
|
16
|
+
readonly resolve: <T>(x: T, opts?: import("@agoric/vow").EUnwrapOptions | undefined) => Promise<Awaited<T>>;
|
|
17
|
+
readonly sendOnly: <T>(x: T, opts?: import("@agoric/vow").EUnwrapOptions | undefined) => ESendOnlyCallableOrMethods<RemoteFunctions<T>>;
|
|
18
|
+
readonly when: <T, TResult1 = import("@agoric/vow").EUnwrap<T>, TResult2 = never>(x: globalThis.ERef<T>, onfulfilled?: ((value: import("@agoric/vow").EUnwrap<T>) => import("@agoric/vow/src/E.js").ERef<TResult1>) | undefined, onrejected?: ((reason: any) => import("@agoric/vow/src/E.js").ERef<TResult2>) | undefined, opts?: import("@agoric/vow").EUnwrapOptions | undefined) => Promise<TResult1 | TResult2>;
|
|
19
|
+
} & {
|
|
20
|
+
when: <T, TResult1 = import("@agoric/vow").EUnwrap<T>, TResult2 = never>(specimenP: T, onFulfilled?: ((value: import("@agoric/vow").EUnwrap<T>) => TResult1 | PromiseLike<TResult1>) | undefined, onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined) => Promise<TResult1 | TResult2>;
|
|
21
|
+
watch: <T = any, TResult1 = T, TResult2 = never, C extends any[] = any[]>(specimenP: import("@agoric/vow").EVow<T>, watcher?: import("@agoric/vow").Watcher<T, TResult1, TResult2, C> | undefined, ...watcherArgs: C) => import("@agoric/vow").Vow<Exclude<TResult1, void> | Exclude<TResult2, void> extends never ? TResult1 : Exclude<TResult1, void> | Exclude<TResult2, void>>;
|
|
22
|
+
};
|
|
23
|
+
when: <T, TResult1 = import("@agoric/vow").EUnwrap<T>, TResult2 = never>(specimenP: T, onFulfilled?: ((value: import("@agoric/vow").EUnwrap<T>) => TResult1 | PromiseLike<TResult1>) | undefined, onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | undefined) => Promise<TResult1 | TResult2>;
|
|
24
|
+
watch: <T = any, TResult1 = T, TResult2 = never, C extends any[] = any[]>(specimenP: import("@agoric/vow").EVow<T>, watcher?: import("@agoric/vow").Watcher<T, TResult1, TResult2, C> | undefined, ...watcherArgs: C) => import("@agoric/vow").Vow<Exclude<TResult1, void> | Exclude<TResult2, void> extends never ? TResult1 : Exclude<TResult1, void> | Exclude<TResult2, void>>;
|
|
25
|
+
makeVowKit: <T>() => import("@agoric/vow").VowKit<T>;
|
|
26
|
+
allVows: (maybeVows: import("@agoric/vow").EVow<unknown>[]) => import("@agoric/vow").Vow<any[]>;
|
|
27
|
+
asVow: <T extends unknown>(fn: (...args: any[]) => import("@agoric/vow").Vow<Awaited<T>> | Awaited<T> | import("@agoric/vow").PromiseVow<T>) => import("@agoric/vow").Vow<Awaited<T>>;
|
|
28
|
+
asPromise: import("@agoric/vow").AsPromiseFunction;
|
|
29
|
+
};
|
|
30
|
+
zone: import("@agoric/base-zone").Zone;
|
|
31
|
+
orchestrate<GuestReturn, HostReturn, GuestContext, HostContext, GuestArgs extends any[], HostArgs extends any[]>(durableName: string, hostCtx: HostContext, guestFn: (guestOrc: import("../orchestration-api.js").Orchestrator, guestCtx: GuestContext, ...args: GuestArgs) => Promise<GuestReturn>): (...args: HostArgs) => Promise<HostReturn>;
|
|
32
|
+
adminAsyncFlow: import("@endo/exo").Guarded<{
|
|
33
|
+
getFailures(): import("@endo/patterns").CopyMap<any, import("@endo/pass-style").Passable>;
|
|
34
|
+
wakeAll(): void;
|
|
35
|
+
getFlowForOutcomeVow(outcomeVow: any): any;
|
|
36
|
+
}>;
|
|
37
|
+
};
|
|
38
|
+
export type OrchestrationPowers = {
|
|
39
|
+
localchain: Remote<LocalChain>;
|
|
40
|
+
orchestrationService: Remote<OrchestrationService>;
|
|
41
|
+
storageNode: Remote<StorageNode>;
|
|
42
|
+
timerService: Remote<TimerService>;
|
|
43
|
+
agoricNames: Remote<NameHub>;
|
|
44
|
+
};
|
|
45
|
+
import type { Baggage } from '@agoric/vat-data';
|
|
46
|
+
import type { LocalChain } from '@agoric/vats/src/localchain.js';
|
|
47
|
+
import type { Remote } from '@agoric/vow';
|
|
48
|
+
import type { OrchestrationService } from '../service.js';
|
|
49
|
+
import type { TimerService } from '@agoric/time';
|
|
50
|
+
import type { NameHub } from '@agoric/vats';
|
|
51
|
+
//# sourceMappingURL=start-helper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"start-helper.d.ts","sourceRoot":"","sources":["start-helper.js"],"names":[],"mappings":"AAwCO,0CALI,GAAG,WACH,OAAO,gBACP,mBAAmB,cACnB,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;wCAmDN,GAAG;;;;4PAmBK,GACjB,4CAA4E,GAAG;;;;;;EAFpF;kCArFY;IACZ,UAAc,EAAE,OAAO,UAAU,CAAC,CAAC;IACnC,oBAAwB,EAAE,OAAO,oBAAoB,CAAC,CAAC;IACvD,WAAe,EAAE,OAAO,WAAW,CAAC,CAAC;IACrC,YAAgB,EAAE,OAAO,YAAY,CAAC,CAAC;IACvC,WAAe,EAAE,OAAO,OAAO,CAAC,CAAC;CAC9B;6BAbsB,kBAAkB;gCAFf,gCAAgC;4BAIpC,aAAa;0CACC,eAAe;kCAJX,cAAc;6BAE/B,cAAc"}
|