@agoric/orchestration 0.1.1-dev-1af1596.0 → 0.1.1-dev-5fb1074.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/package.json +18 -17
- package/tools/ibc-mocks.d.ts +116 -0
- package/tools/ibc-mocks.d.ts.map +1 -0
- package/tools/ibc-mocks.ts +262 -0
- package/tools/make-test-address.d.ts +2 -0
- package/tools/make-test-address.d.ts.map +1 -0
- package/tools/make-test-address.js +21 -0
- package/tools/protobuf-decoder.d.ts +19 -0
- package/tools/protobuf-decoder.d.ts.map +1 -0
- package/tools/protobuf-decoder.js +153 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agoric/orchestration",
|
|
3
|
-
"version": "0.1.1-dev-
|
|
3
|
+
"version": "0.1.1-dev-5fb1074.0+5fb1074",
|
|
4
4
|
"description": "Chain abstraction for Agoric's orchestration clients",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -33,19 +33,19 @@
|
|
|
33
33
|
},
|
|
34
34
|
"homepage": "https://github.com/Agoric/agoric-sdk#readme",
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@agoric/async-flow": "0.1.1-dev-
|
|
37
|
-
"@agoric/cosmic-proto": "0.4.1-dev-
|
|
38
|
-
"@agoric/ertp": "0.16.3-dev-
|
|
39
|
-
"@agoric/internal": "0.3.3-dev-
|
|
40
|
-
"@agoric/network": "0.1.1-dev-
|
|
41
|
-
"@agoric/notifier": "0.6.3-dev-
|
|
42
|
-
"@agoric/store": "0.9.3-dev-
|
|
43
|
-
"@agoric/time": "0.3.3-dev-
|
|
44
|
-
"@agoric/vat-data": "0.5.3-dev-
|
|
45
|
-
"@agoric/vats": "0.15.2-dev-
|
|
46
|
-
"@agoric/vow": "0.1.1-dev-
|
|
47
|
-
"@agoric/zoe": "0.26.3-dev-
|
|
48
|
-
"@agoric/zone": "0.2.3-dev-
|
|
36
|
+
"@agoric/async-flow": "0.1.1-dev-5fb1074.0+5fb1074",
|
|
37
|
+
"@agoric/cosmic-proto": "0.4.1-dev-5fb1074.0+5fb1074",
|
|
38
|
+
"@agoric/ertp": "0.16.3-dev-5fb1074.0+5fb1074",
|
|
39
|
+
"@agoric/internal": "0.3.3-dev-5fb1074.0+5fb1074",
|
|
40
|
+
"@agoric/network": "0.1.1-dev-5fb1074.0+5fb1074",
|
|
41
|
+
"@agoric/notifier": "0.6.3-dev-5fb1074.0+5fb1074",
|
|
42
|
+
"@agoric/store": "0.9.3-dev-5fb1074.0+5fb1074",
|
|
43
|
+
"@agoric/time": "0.3.3-dev-5fb1074.0+5fb1074",
|
|
44
|
+
"@agoric/vat-data": "0.5.3-dev-5fb1074.0+5fb1074",
|
|
45
|
+
"@agoric/vats": "0.15.2-dev-5fb1074.0+5fb1074",
|
|
46
|
+
"@agoric/vow": "0.1.1-dev-5fb1074.0+5fb1074",
|
|
47
|
+
"@agoric/zoe": "0.26.3-dev-5fb1074.0+5fb1074",
|
|
48
|
+
"@agoric/zone": "0.2.3-dev-5fb1074.0+5fb1074",
|
|
49
49
|
"@endo/base64": "^1.0.9",
|
|
50
50
|
"@endo/errors": "^1.2.9",
|
|
51
51
|
"@endo/far": "^1.1.10",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"@noble/hashes": "^1.5.0"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@agoric/swingset-liveslots": "0.10.3-dev-
|
|
57
|
+
"@agoric/swingset-liveslots": "0.10.3-dev-5fb1074.0+5fb1074",
|
|
58
58
|
"@chain-registry/client": "^1.47.4",
|
|
59
59
|
"@cosmjs/amino": "^0.32.3",
|
|
60
60
|
"@cosmjs/proto-signing": "^0.32.3",
|
|
@@ -88,7 +88,8 @@
|
|
|
88
88
|
"files": [
|
|
89
89
|
"*.js",
|
|
90
90
|
"*.ts",
|
|
91
|
-
"src"
|
|
91
|
+
"src",
|
|
92
|
+
"tools"
|
|
92
93
|
],
|
|
93
94
|
"publishConfig": {
|
|
94
95
|
"access": "public"
|
|
@@ -96,5 +97,5 @@
|
|
|
96
97
|
"typeCoverage": {
|
|
97
98
|
"atLeast": 97.77
|
|
98
99
|
},
|
|
99
|
-
"gitHead": "
|
|
100
|
+
"gitHead": "5fb1074c907ab4049321337a5379fa25c79ad237"
|
|
100
101
|
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/** @file Tools to support making IBC mocks */
|
|
2
|
+
import { type JsonSafe } from '@agoric/cosmic-proto';
|
|
3
|
+
import { TxBody } from '@agoric/cosmic-proto/cosmos/tx/v1beta1/tx.js';
|
|
4
|
+
import { Any } from '@agoric/cosmic-proto/google/protobuf/any.js';
|
|
5
|
+
import type { PacketSDKType } from '@agoric/cosmic-proto/ibc/core/channel/v1/channel.js';
|
|
6
|
+
import { RequestQuery, ResponseQuery } from '@agoric/cosmic-proto/tendermint/abci/types.js';
|
|
7
|
+
import type { IBCChannelID, IBCEvent, VTransferIBCEvent } from '@agoric/vats';
|
|
8
|
+
import type { ChainAddress } from '../src/orchestration-api.js';
|
|
9
|
+
interface EncoderCommon<T> {
|
|
10
|
+
encode: (message: T) => {
|
|
11
|
+
finish: () => Uint8Array;
|
|
12
|
+
};
|
|
13
|
+
fromPartial: (partial: Partial<T>) => T;
|
|
14
|
+
typeUrl: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Build a response "packet bytes string" we'd expect to see from a Msg
|
|
18
|
+
* Response
|
|
19
|
+
*
|
|
20
|
+
* XXX support multiple responses in a single message
|
|
21
|
+
*
|
|
22
|
+
* @param Encoder
|
|
23
|
+
* @param message
|
|
24
|
+
*/
|
|
25
|
+
export declare function buildMsgResponseString<T>(Encoder: EncoderCommon<T>, message: Partial<T>): string;
|
|
26
|
+
/**
|
|
27
|
+
* Build an example error packet for a failed Tx Msg
|
|
28
|
+
* @param msg
|
|
29
|
+
*/
|
|
30
|
+
export declare function buildMsgErrorString(msg?: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Build a response "packet bytes string" we'd expect to see from a Query
|
|
33
|
+
* request
|
|
34
|
+
*
|
|
35
|
+
* XXX accept multiple queries at once
|
|
36
|
+
*
|
|
37
|
+
* @param Encoder
|
|
38
|
+
* @param query
|
|
39
|
+
* @param opts
|
|
40
|
+
*/
|
|
41
|
+
export declare function buildQueryResponseString<T>(Encoder: EncoderCommon<T>, query: Partial<T>, opts?: Omit<ResponseQuery, 'key'>): string;
|
|
42
|
+
/**
|
|
43
|
+
* Build a tx packet string for the mocked dibc bridge handler
|
|
44
|
+
* @param msgs
|
|
45
|
+
* @returns {string}
|
|
46
|
+
*/
|
|
47
|
+
export declare function buildTxPacketString(msgs: {
|
|
48
|
+
value: Uint8Array;
|
|
49
|
+
typeUrl: string;
|
|
50
|
+
}[]): string;
|
|
51
|
+
/**
|
|
52
|
+
* Parse an outgoing ica tx packet. Useful for testing when inspecting
|
|
53
|
+
* outgoing dibc bridge messages.
|
|
54
|
+
*
|
|
55
|
+
* @param b64 base64 encoded string
|
|
56
|
+
*/
|
|
57
|
+
export declare const parseOutgoingTxPacket: (b64: string) => TxBody;
|
|
58
|
+
/**
|
|
59
|
+
* Build a query packet string for the mocked dibc bridge handler
|
|
60
|
+
* @param msgs
|
|
61
|
+
* @param opts
|
|
62
|
+
* @returns {string}
|
|
63
|
+
*/
|
|
64
|
+
export declare function buildQueryPacketString(msgs: Any[], opts?: Partial<Omit<RequestQuery, 'path' | 'data'>>): string;
|
|
65
|
+
type BuildVTransferEventParams = {
|
|
66
|
+
event?: VTransferIBCEvent['event'];
|
|
67
|
+
sender?: ChainAddress['value'];
|
|
68
|
+
receiver?: ChainAddress['value'];
|
|
69
|
+
target?: ChainAddress['value'];
|
|
70
|
+
amount?: bigint;
|
|
71
|
+
denom?: string;
|
|
72
|
+
destinationChannel?: IBCChannelID;
|
|
73
|
+
sourceChannel?: IBCChannelID;
|
|
74
|
+
sequence?: PacketSDKType['sequence'] | JsonSafe<PacketSDKType['sequence']>;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* `buildVTransferEvent` can be used with `transferBridge` to simulate incoming
|
|
78
|
+
* and outgoing IBC fungible tokens transfers to a LocalChain account.
|
|
79
|
+
*
|
|
80
|
+
* It defaults to simulating incoming transfers. To simulate an outgoing one,
|
|
81
|
+
* ensure `sender=agoric1fakeLCAAddress` and this after LocalChainBridge
|
|
82
|
+
* receives the outgoing MsgTransfer,
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```js
|
|
86
|
+
* const { mocks: { transferBridge } = await commonSetup(t);
|
|
87
|
+
* await E(transferBridge).fromBridge(
|
|
88
|
+
* buildVTransferEvent({
|
|
89
|
+
* receiver: 'agoric1fakeLCAAddress',
|
|
90
|
+
* amount: 10n,
|
|
91
|
+
* denom: 'uatom',
|
|
92
|
+
* }),
|
|
93
|
+
* );
|
|
94
|
+
* ```
|
|
95
|
+
*
|
|
96
|
+
* XXX integrate vlocalchain and vtransfer ScopedBridgeManagers
|
|
97
|
+
* in test supports.
|
|
98
|
+
*
|
|
99
|
+
* @param {{BuildVTransferEventParams}} args
|
|
100
|
+
*/
|
|
101
|
+
export declare const buildVTransferEvent: ({ event, sender, receiver, target, amount, denom, destinationChannel, sourceChannel, sequence, }?: BuildVTransferEventParams) => VTransferIBCEvent;
|
|
102
|
+
export declare function createMockAckMap(mockMap: Record<string, {
|
|
103
|
+
msg: string;
|
|
104
|
+
ack: string;
|
|
105
|
+
}>): {};
|
|
106
|
+
/**
|
|
107
|
+
* Simulate an IBC channelCloseConfirm event. This can be used to simulate an
|
|
108
|
+
* ICA channel closing for an unexpected reason from a remote chain, _or
|
|
109
|
+
* anything besides the Connection holder calling `.close()`_. If `close()` is
|
|
110
|
+
* called, we'd instead expect to see a Downcall for channelCloseInit.
|
|
111
|
+
*
|
|
112
|
+
* @param {Pick<IBCEvent<'channelCloseConfirm'>, 'portID' | 'channelID'>} event
|
|
113
|
+
*/
|
|
114
|
+
export declare const buildChannelCloseConfirmEvent: ({ channelID, portID, }?: Partial<IBCEvent<"channelCloseConfirm">>) => Partial<IBCEvent<"channelCloseConfirm">>;
|
|
115
|
+
export {};
|
|
116
|
+
//# sourceMappingURL=ibc-mocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ibc-mocks.d.ts","sourceRoot":"","sources":["ibc-mocks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/** @file Tools to support making IBC mocks */
|
|
2
|
+
import { type JsonSafe, toRequestQueryJson } from '@agoric/cosmic-proto';
|
|
3
|
+
import { TxBody } from '@agoric/cosmic-proto/cosmos/tx/v1beta1/tx.js';
|
|
4
|
+
import { Any } from '@agoric/cosmic-proto/google/protobuf/any.js';
|
|
5
|
+
import { FungibleTokenPacketData } from '@agoric/cosmic-proto/ibc/applications/transfer/v2/packet.js';
|
|
6
|
+
import type { PacketSDKType } from '@agoric/cosmic-proto/ibc/core/channel/v1/channel.js';
|
|
7
|
+
import { CosmosResponse } from '@agoric/cosmic-proto/icq/v1/packet.js';
|
|
8
|
+
import {
|
|
9
|
+
RequestQuery,
|
|
10
|
+
ResponseQuery,
|
|
11
|
+
} from '@agoric/cosmic-proto/tendermint/abci/types.js';
|
|
12
|
+
import {
|
|
13
|
+
IBC_EVENT,
|
|
14
|
+
VTRANSFER_IBC_EVENT,
|
|
15
|
+
} from '@agoric/internal/src/action-types.js';
|
|
16
|
+
import type {
|
|
17
|
+
IBCChannelID,
|
|
18
|
+
IBCEvent,
|
|
19
|
+
IBCPacket,
|
|
20
|
+
VTransferIBCEvent,
|
|
21
|
+
} from '@agoric/vats';
|
|
22
|
+
import { LOCALCHAIN_DEFAULT_ADDRESS } from '@agoric/vats/tools/fake-bridge.js';
|
|
23
|
+
import { atob, btoa, decodeBase64, encodeBase64 } from '@endo/base64';
|
|
24
|
+
import type { ChainAddress } from '../src/orchestration-api.js';
|
|
25
|
+
import { makeQueryPacket, makeTxPacket } from '../src/utils/packet.js';
|
|
26
|
+
|
|
27
|
+
interface EncoderCommon<T> {
|
|
28
|
+
encode: (message: T) => {
|
|
29
|
+
finish: () => Uint8Array;
|
|
30
|
+
};
|
|
31
|
+
fromPartial: (partial: Partial<T>) => T;
|
|
32
|
+
typeUrl: string;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const toPacket = (obj: Record<string, any>): string =>
|
|
36
|
+
btoa(JSON.stringify(obj));
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Build a response "packet bytes string" we'd expect to see from a Msg
|
|
40
|
+
* Response
|
|
41
|
+
*
|
|
42
|
+
* XXX support multiple responses in a single message
|
|
43
|
+
*
|
|
44
|
+
* @param Encoder
|
|
45
|
+
* @param message
|
|
46
|
+
*/
|
|
47
|
+
export function buildMsgResponseString<T>(
|
|
48
|
+
Encoder: EncoderCommon<T>,
|
|
49
|
+
message: Partial<T>,
|
|
50
|
+
): string {
|
|
51
|
+
const encodedMsg = Encoder.encode(Encoder.fromPartial(message)).finish();
|
|
52
|
+
|
|
53
|
+
// cosmos-sdk double Any encodes
|
|
54
|
+
const encodedAny = Any.encode(
|
|
55
|
+
Any.fromPartial({
|
|
56
|
+
value: Any.encode(
|
|
57
|
+
Any.fromPartial({
|
|
58
|
+
typeUrl: Encoder.typeUrl,
|
|
59
|
+
value: encodedMsg,
|
|
60
|
+
}),
|
|
61
|
+
).finish(),
|
|
62
|
+
}),
|
|
63
|
+
).finish();
|
|
64
|
+
|
|
65
|
+
return toPacket({
|
|
66
|
+
result: encodeBase64(encodedAny),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Build an example error packet for a failed Tx Msg
|
|
72
|
+
* @param msg
|
|
73
|
+
*/
|
|
74
|
+
export function buildMsgErrorString(
|
|
75
|
+
msg = 'ABCI code: 5: error handling packet: see events for details',
|
|
76
|
+
): string {
|
|
77
|
+
return toPacket({
|
|
78
|
+
error: msg,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Build a response "packet bytes string" we'd expect to see from a Query
|
|
84
|
+
* request
|
|
85
|
+
*
|
|
86
|
+
* XXX accept multiple queries at once
|
|
87
|
+
*
|
|
88
|
+
* @param Encoder
|
|
89
|
+
* @param query
|
|
90
|
+
* @param opts
|
|
91
|
+
*/
|
|
92
|
+
export function buildQueryResponseString<T>(
|
|
93
|
+
Encoder: EncoderCommon<T>,
|
|
94
|
+
query: Partial<T>,
|
|
95
|
+
opts: Omit<ResponseQuery, 'key'> = {
|
|
96
|
+
value: new Uint8Array(),
|
|
97
|
+
height: 0n,
|
|
98
|
+
index: 0n,
|
|
99
|
+
code: 0,
|
|
100
|
+
log: '',
|
|
101
|
+
info: '',
|
|
102
|
+
codespace: '',
|
|
103
|
+
},
|
|
104
|
+
): string {
|
|
105
|
+
const encodedResp = CosmosResponse.encode(
|
|
106
|
+
CosmosResponse.fromPartial({
|
|
107
|
+
responses: [
|
|
108
|
+
{
|
|
109
|
+
key: Encoder.encode(Encoder.fromPartial(query)).finish(),
|
|
110
|
+
...opts,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
}),
|
|
114
|
+
).finish();
|
|
115
|
+
|
|
116
|
+
return toPacket({
|
|
117
|
+
result: toPacket({ data: encodeBase64(encodedResp) }),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Build a tx packet string for the mocked dibc bridge handler
|
|
123
|
+
* @param msgs
|
|
124
|
+
* @returns {string}
|
|
125
|
+
*/
|
|
126
|
+
export function buildTxPacketString(
|
|
127
|
+
msgs: { value: Uint8Array; typeUrl: string }[],
|
|
128
|
+
): string {
|
|
129
|
+
return btoa(makeTxPacket(msgs.map(Any.toJSON)));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Parse an outgoing ica tx packet. Useful for testing when inspecting
|
|
134
|
+
* outgoing dibc bridge messages.
|
|
135
|
+
*
|
|
136
|
+
* @param b64 base64 encoded string
|
|
137
|
+
*/
|
|
138
|
+
export const parseOutgoingTxPacket = (b64: string) => {
|
|
139
|
+
return TxBody.decode(decodeBase64(JSON.parse(atob(b64)).data));
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Build a query packet string for the mocked dibc bridge handler
|
|
144
|
+
* @param msgs
|
|
145
|
+
* @param opts
|
|
146
|
+
* @returns {string}
|
|
147
|
+
*/
|
|
148
|
+
export function buildQueryPacketString(
|
|
149
|
+
msgs: Any[],
|
|
150
|
+
opts: Partial<Omit<RequestQuery, 'path' | 'data'>> = {},
|
|
151
|
+
): string {
|
|
152
|
+
return btoa(makeQueryPacket(msgs.map(msg => toRequestQueryJson(msg, opts))));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
type BuildVTransferEventParams = {
|
|
156
|
+
event?: VTransferIBCEvent['event'];
|
|
157
|
+
/* defaults to cosmos1AccAddress. set to `agoric1fakeLCAAddress` to simulate an outgoing transfer event */
|
|
158
|
+
sender?: ChainAddress['value'];
|
|
159
|
+
/* defaults to agoric1fakeLCAAddress. set to a different value to simulate an outgoing transfer event */
|
|
160
|
+
receiver?: ChainAddress['value'];
|
|
161
|
+
target?: ChainAddress['value'];
|
|
162
|
+
amount?: bigint;
|
|
163
|
+
denom?: string;
|
|
164
|
+
destinationChannel?: IBCChannelID;
|
|
165
|
+
sourceChannel?: IBCChannelID;
|
|
166
|
+
/* support bigint and string, to facilitate bootstrap testing */
|
|
167
|
+
sequence?: PacketSDKType['sequence'] | JsonSafe<PacketSDKType['sequence']>;
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* `buildVTransferEvent` can be used with `transferBridge` to simulate incoming
|
|
172
|
+
* and outgoing IBC fungible tokens transfers to a LocalChain account.
|
|
173
|
+
*
|
|
174
|
+
* It defaults to simulating incoming transfers. To simulate an outgoing one,
|
|
175
|
+
* ensure `sender=agoric1fakeLCAAddress` and this after LocalChainBridge
|
|
176
|
+
* receives the outgoing MsgTransfer,
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```js
|
|
180
|
+
* const { mocks: { transferBridge } = await commonSetup(t);
|
|
181
|
+
* await E(transferBridge).fromBridge(
|
|
182
|
+
* buildVTransferEvent({
|
|
183
|
+
* receiver: 'agoric1fakeLCAAddress',
|
|
184
|
+
* amount: 10n,
|
|
185
|
+
* denom: 'uatom',
|
|
186
|
+
* }),
|
|
187
|
+
* );
|
|
188
|
+
* ```
|
|
189
|
+
*
|
|
190
|
+
* XXX integrate vlocalchain and vtransfer ScopedBridgeManagers
|
|
191
|
+
* in test supports.
|
|
192
|
+
*
|
|
193
|
+
* @param {{BuildVTransferEventParams}} args
|
|
194
|
+
*/
|
|
195
|
+
export const buildVTransferEvent = ({
|
|
196
|
+
event = 'acknowledgementPacket' as const,
|
|
197
|
+
sender = 'cosmos1AccAddress',
|
|
198
|
+
receiver = LOCALCHAIN_DEFAULT_ADDRESS,
|
|
199
|
+
target = LOCALCHAIN_DEFAULT_ADDRESS,
|
|
200
|
+
amount = 10n,
|
|
201
|
+
denom = 'uatom',
|
|
202
|
+
destinationChannel = 'channel-0' as IBCChannelID,
|
|
203
|
+
sourceChannel = 'channel-405' as IBCChannelID,
|
|
204
|
+
sequence = 0n,
|
|
205
|
+
}: BuildVTransferEventParams = {}): VTransferIBCEvent => ({
|
|
206
|
+
type: VTRANSFER_IBC_EVENT,
|
|
207
|
+
blockHeight: 0,
|
|
208
|
+
blockTime: 0,
|
|
209
|
+
event,
|
|
210
|
+
acknowledgement: btoa(JSON.stringify({ result: 'AQ==' })),
|
|
211
|
+
relayer: 'agoric123',
|
|
212
|
+
target,
|
|
213
|
+
packet: {
|
|
214
|
+
data: btoa(
|
|
215
|
+
JSON.stringify(
|
|
216
|
+
FungibleTokenPacketData.fromPartial({
|
|
217
|
+
amount: String(amount),
|
|
218
|
+
denom,
|
|
219
|
+
sender,
|
|
220
|
+
receiver,
|
|
221
|
+
}),
|
|
222
|
+
),
|
|
223
|
+
),
|
|
224
|
+
destination_channel: destinationChannel,
|
|
225
|
+
source_channel: sourceChannel,
|
|
226
|
+
destination_port: 'transfer',
|
|
227
|
+
source_port: 'transfer',
|
|
228
|
+
sequence,
|
|
229
|
+
} as IBCPacket,
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
export function createMockAckMap(
|
|
233
|
+
mockMap: Record<string, { msg: string; ack: string }>,
|
|
234
|
+
) {
|
|
235
|
+
const res = Object.values(mockMap).reduce((acc, { msg, ack }) => {
|
|
236
|
+
acc[msg] = ack;
|
|
237
|
+
return acc;
|
|
238
|
+
}, {});
|
|
239
|
+
return res;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Simulate an IBC channelCloseConfirm event. This can be used to simulate an
|
|
244
|
+
* ICA channel closing for an unexpected reason from a remote chain, _or
|
|
245
|
+
* anything besides the Connection holder calling `.close()`_. If `close()` is
|
|
246
|
+
* called, we'd instead expect to see a Downcall for channelCloseInit.
|
|
247
|
+
*
|
|
248
|
+
* @param {Pick<IBCEvent<'channelCloseConfirm'>, 'portID' | 'channelID'>} event
|
|
249
|
+
*/
|
|
250
|
+
export const buildChannelCloseConfirmEvent = ({
|
|
251
|
+
channelID = 'channel-0',
|
|
252
|
+
portID = 'icacontroller-1',
|
|
253
|
+
}: Partial<IBCEvent<'channelCloseConfirm'>> = {}): Partial<
|
|
254
|
+
IBCEvent<'channelCloseConfirm'>
|
|
255
|
+
> => ({
|
|
256
|
+
blockHeight: 0,
|
|
257
|
+
blockTime: 0,
|
|
258
|
+
channelID,
|
|
259
|
+
event: 'channelCloseConfirm',
|
|
260
|
+
portID,
|
|
261
|
+
type: IBC_EVENT,
|
|
262
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"make-test-address.d.ts","sourceRoot":"","sources":["make-test-address.js"],"names":[],"mappings":"AASO,wCALI,MAAM,WACN,MAAM,eACN,MAAM,GACJ,MAAM,CAalB"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
import { bech32 } from 'bech32';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @param {number} index
|
|
6
|
+
* @param {string} prefix
|
|
7
|
+
* @param {number} byteLength
|
|
8
|
+
* @returns {string} a mock bech32 address for tests
|
|
9
|
+
*/
|
|
10
|
+
export const makeTestAddress = (
|
|
11
|
+
index = 0,
|
|
12
|
+
prefix = 'agoric',
|
|
13
|
+
byteLength = 20,
|
|
14
|
+
) => {
|
|
15
|
+
// create a simple 20-byte array (common address length)
|
|
16
|
+
const bytes = new Uint8Array(byteLength).fill(0);
|
|
17
|
+
// if index provided, put it in the first byte
|
|
18
|
+
if (index !== 0) bytes[0] = Number(index);
|
|
19
|
+
const words = bech32.toWords(bytes);
|
|
20
|
+
return bech32.encode(prefix, words);
|
|
21
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Decodes a protobuf message from the given buffer.
|
|
3
|
+
*
|
|
4
|
+
* @param {Buffer} buffer
|
|
5
|
+
*/
|
|
6
|
+
export function decodeProtobuf(buffer: Buffer): {
|
|
7
|
+
value: {};
|
|
8
|
+
bytesRead: number;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Decodes a protobuf message from the given base64-encoded data.
|
|
12
|
+
*
|
|
13
|
+
* @param {string} base64String
|
|
14
|
+
*/
|
|
15
|
+
export function decodeProtobufBase64(base64String: string): {
|
|
16
|
+
value: {};
|
|
17
|
+
bytesRead: number;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=protobuf-decoder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protobuf-decoder.d.ts","sourceRoot":"","sources":["protobuf-decoder.js"],"names":[],"mappings":"AA8HA;;;;GAIG;AACH,uCAFW,MAAM;;;EAchB;AACD;;;;GAIG;AACH,mDAFW,MAAM;;;EAKhB"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/* eslint-env node */
|
|
2
|
+
/* eslint-disable -- generated by Sonnet, easier to leave alone */
|
|
3
|
+
|
|
4
|
+
const WIRE_TYPES = {
|
|
5
|
+
VARINT: 0,
|
|
6
|
+
FIXED64: 1,
|
|
7
|
+
LENGTH_DELIMITED: 2,
|
|
8
|
+
START_GROUP: 3,
|
|
9
|
+
END_GROUP: 4,
|
|
10
|
+
FIXED32: 5,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
function decodeVarint(buffer, offset) {
|
|
14
|
+
let result = 0n;
|
|
15
|
+
let shift = 0;
|
|
16
|
+
let byte;
|
|
17
|
+
|
|
18
|
+
do {
|
|
19
|
+
if (offset >= buffer.length) {
|
|
20
|
+
throw new Error('Buffer overflow while decoding varint');
|
|
21
|
+
}
|
|
22
|
+
byte = buffer[offset];
|
|
23
|
+
result |= BigInt(byte & 0x7f) << BigInt(shift);
|
|
24
|
+
shift += 7;
|
|
25
|
+
offset++;
|
|
26
|
+
} while (byte & 0x80);
|
|
27
|
+
|
|
28
|
+
return { value: result, bytesRead: shift / 7 };
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function decodeFixed32(buffer, offset) {
|
|
32
|
+
if (offset + 4 > buffer.length) {
|
|
33
|
+
throw new Error('Buffer overflow while decoding fixed32');
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
value: buffer.readUInt32LE(offset),
|
|
37
|
+
bytesRead: 4,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function decodeFixed64(buffer, offset) {
|
|
42
|
+
if (offset + 8 > buffer.length) {
|
|
43
|
+
throw new Error('Buffer overflow while decoding fixed64');
|
|
44
|
+
}
|
|
45
|
+
const low = buffer.readUInt32LE(offset);
|
|
46
|
+
const high = buffer.readUInt32LE(offset + 4);
|
|
47
|
+
return {
|
|
48
|
+
value: BigInt(high) * 2n ** 32n + BigInt(low),
|
|
49
|
+
bytesRead: 8,
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function decodeString(buffer, offset, length) {
|
|
54
|
+
if (offset + length > buffer.length) {
|
|
55
|
+
throw new Error('Buffer overflow while decoding string');
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
value: buffer.toString('utf8', offset, offset + length),
|
|
59
|
+
bytesRead: length,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function decodeField(buffer, offset) {
|
|
64
|
+
const tag = decodeVarint(buffer, offset);
|
|
65
|
+
offset += tag.bytesRead;
|
|
66
|
+
|
|
67
|
+
const fieldNumber = Number(tag.value >> 3n);
|
|
68
|
+
const wireType = Number(tag.value & 0x7n);
|
|
69
|
+
|
|
70
|
+
let value;
|
|
71
|
+
let bytesRead;
|
|
72
|
+
|
|
73
|
+
switch (wireType) {
|
|
74
|
+
case WIRE_TYPES.VARINT:
|
|
75
|
+
({ value, bytesRead } = decodeVarint(buffer, offset));
|
|
76
|
+
break;
|
|
77
|
+
case WIRE_TYPES.FIXED64:
|
|
78
|
+
({ value, bytesRead } = decodeFixed64(buffer, offset));
|
|
79
|
+
break;
|
|
80
|
+
case WIRE_TYPES.LENGTH_DELIMITED:
|
|
81
|
+
const length = decodeVarint(buffer, offset);
|
|
82
|
+
offset += length.bytesRead;
|
|
83
|
+
// Try to decode as a nested message first
|
|
84
|
+
try {
|
|
85
|
+
({ value, bytesRead } = decodeProtobuf(
|
|
86
|
+
buffer.slice(offset, offset + Number(length.value)),
|
|
87
|
+
));
|
|
88
|
+
} catch (e) {
|
|
89
|
+
// If it fails, decode as a string
|
|
90
|
+
({ value, bytesRead } = decodeString(
|
|
91
|
+
buffer,
|
|
92
|
+
offset,
|
|
93
|
+
Number(length.value),
|
|
94
|
+
));
|
|
95
|
+
}
|
|
96
|
+
bytesRead += length.bytesRead;
|
|
97
|
+
break;
|
|
98
|
+
case WIRE_TYPES.FIXED32:
|
|
99
|
+
({ value, bytesRead } = decodeFixed32(buffer, offset));
|
|
100
|
+
break;
|
|
101
|
+
default:
|
|
102
|
+
throw new Error(`Unsupported wire type: ${wireType}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
fieldNumber,
|
|
107
|
+
wireType,
|
|
108
|
+
value,
|
|
109
|
+
bytesRead: tag.bytesRead + bytesRead,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function getFieldName(fieldNumber, wireType) {
|
|
114
|
+
const typePrefix =
|
|
115
|
+
wireType === WIRE_TYPES.LENGTH_DELIMITED
|
|
116
|
+
? 'subMessage'
|
|
117
|
+
: wireType === WIRE_TYPES.VARINT
|
|
118
|
+
? 'int'
|
|
119
|
+
: wireType === WIRE_TYPES.FIXED32
|
|
120
|
+
? 'fixed32'
|
|
121
|
+
: wireType === WIRE_TYPES.FIXED64
|
|
122
|
+
? 'fixed64'
|
|
123
|
+
: 'string';
|
|
124
|
+
return `${typePrefix}_${fieldNumber}`;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Decodes a protobuf message from the given buffer.
|
|
129
|
+
*
|
|
130
|
+
* @param {Buffer} buffer
|
|
131
|
+
*/
|
|
132
|
+
export function decodeProtobuf(buffer) {
|
|
133
|
+
let offset = 0;
|
|
134
|
+
const message = {};
|
|
135
|
+
|
|
136
|
+
while (offset < buffer.length) {
|
|
137
|
+
const field = decodeField(buffer, offset);
|
|
138
|
+
const fieldName = getFieldName(field.fieldNumber, field.wireType);
|
|
139
|
+
message[fieldName] = field.value;
|
|
140
|
+
offset += field.bytesRead;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return { value: message, bytesRead: offset };
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Decodes a protobuf message from the given base64-encoded data.
|
|
147
|
+
*
|
|
148
|
+
* @param {string} base64String
|
|
149
|
+
*/
|
|
150
|
+
export function decodeProtobufBase64(base64String) {
|
|
151
|
+
const buffer = Buffer.from(base64String, 'base64');
|
|
152
|
+
return decodeProtobuf(buffer);
|
|
153
|
+
}
|