schemos 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{telescope.d.ts → adapters/telescope.d.ts} +3 -3
- package/dist/adapters/telescope.d.ts.map +1 -0
- package/dist/{telescope.js → adapters/telescope.js} +5 -6
- package/dist/adapters/telescope.js.map +1 -0
- package/dist/adapters/telescope.test.d.ts.map +1 -0
- package/dist/{telescope.test.js → adapters/telescope.test.js} +11 -11
- package/dist/adapters/telescope.test.js.map +1 -0
- package/dist/client.test-d.js +2 -2
- package/dist/client.test-d.js.map +1 -1
- package/dist/contract.bench-d.js +32 -10
- package/dist/contract.bench-d.js.map +1 -1
- package/dist/contract.d.ts +3 -5
- package/dist/contract.d.ts.map +1 -1
- package/dist/contract.js +18 -15
- package/dist/contract.js.map +1 -1
- package/dist/contract.test.js +49 -1
- package/dist/contract.test.js.map +1 -1
- package/dist/encoding/index.d.ts +2 -0
- package/dist/encoding/index.d.ts.map +1 -0
- package/dist/encoding/index.js +2 -0
- package/dist/encoding/index.js.map +1 -0
- package/dist/encoding/json.d.ts +58 -0
- package/dist/encoding/json.d.ts.map +1 -0
- package/dist/encoding/json.js +95 -0
- package/dist/encoding/json.js.map +1 -0
- package/dist/encoding/json.test.d.ts +2 -0
- package/dist/encoding/json.test.d.ts.map +1 -0
- package/dist/encoding/json.test.js +49 -0
- package/dist/encoding/json.test.js.map +1 -0
- package/dist/formats.d.ts +33 -0
- package/dist/formats.d.ts.map +1 -0
- package/dist/formats.js +38 -0
- package/dist/formats.js.map +1 -0
- package/dist/formats.test.d.ts +2 -0
- package/dist/formats.test.d.ts.map +1 -0
- package/dist/formats.test.js +124 -0
- package/dist/formats.test.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/msg-compat.test-d.d.ts +13 -0
- package/dist/msg-compat.test-d.d.ts.map +1 -0
- package/dist/msg-compat.test-d.js +68 -0
- package/dist/msg-compat.test-d.js.map +1 -0
- package/dist/msg.d.ts +96 -0
- package/dist/msg.d.ts.map +1 -0
- package/dist/msg.js +98 -0
- package/dist/msg.js.map +1 -0
- package/dist/msg.test-d.d.ts +2 -0
- package/dist/msg.test-d.d.ts.map +1 -0
- package/dist/msg.test-d.js +121 -0
- package/dist/msg.test-d.js.map +1 -0
- package/dist/msg.test.d.ts +2 -0
- package/dist/msg.test.d.ts.map +1 -0
- package/dist/msg.test.js +177 -0
- package/dist/msg.test.js.map +1 -0
- package/dist/patches/fixed-tuple.test-d.d.ts +2 -0
- package/dist/patches/fixed-tuple.test-d.d.ts.map +1 -0
- package/dist/patches/fixed-tuple.test-d.js +76 -0
- package/dist/patches/fixed-tuple.test-d.js.map +1 -0
- package/dist/schemas/cw20/index.d.ts +152 -1
- package/dist/schemas/cw20/index.d.ts.map +1 -1
- package/dist/schemas/cw20/index.js +3 -1
- package/dist/schemas/cw20/index.js.map +1 -1
- package/dist/schemas/cw20/instantiate.d.ts +155 -0
- package/dist/schemas/cw20/instantiate.d.ts.map +1 -0
- package/dist/schemas/cw20/instantiate.js +175 -0
- package/dist/schemas/cw20/instantiate.js.map +1 -0
- package/dist/schemas/cw721/index.d.ts +96 -1
- package/dist/schemas/cw721/index.d.ts.map +1 -1
- package/dist/schemas/cw721/index.js +3 -1
- package/dist/schemas/cw721/index.js.map +1 -1
- package/dist/schemas/cw721/instantiate.d.ts +99 -0
- package/dist/schemas/cw721/instantiate.d.ts.map +1 -0
- package/dist/schemas/cw721/instantiate.js +112 -0
- package/dist/schemas/cw721/instantiate.js.map +1 -0
- package/dist/schemas/schemas.test-d.js +55 -0
- package/dist/schemas/schemas.test-d.js.map +1 -1
- package/dist/wallet-compat.test-d.js +11 -11
- package/dist/wallet-compat.test-d.js.map +1 -1
- package/package.json +7 -17
- package/dist/telescope.d.ts.map +0 -1
- package/dist/telescope.js.map +0 -1
- package/dist/telescope.test.d.ts.map +0 -1
- package/dist/telescope.test.js.map +0 -1
- /package/dist/{telescope.test.d.ts → adapters/telescope.test.d.ts} +0 -0
package/dist/msg.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Ajv } from 'ajv';
|
|
2
|
+
import { cosmwasmFormats } from './formats.js';
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Level 2: buildMsg — validated envelope builder
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
/** Module-level Ajv validator cache. WeakMap allows GC of out-of-scope schemas. */
|
|
7
|
+
const validatorCache = new WeakMap();
|
|
8
|
+
function getValidator(schema) {
|
|
9
|
+
const key = schema;
|
|
10
|
+
let cached = validatorCache.get(key);
|
|
11
|
+
if (!cached) {
|
|
12
|
+
const ajv = new Ajv();
|
|
13
|
+
for (const [name, def] of Object.entries(cosmwasmFormats)) {
|
|
14
|
+
ajv.addFormat(name, def);
|
|
15
|
+
}
|
|
16
|
+
const validate = ajv.compile(schema);
|
|
17
|
+
cached = { validate, ajv };
|
|
18
|
+
validatorCache.set(key, cached);
|
|
19
|
+
}
|
|
20
|
+
return cached;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Create a typed message builder from a JSON Schema.
|
|
24
|
+
*
|
|
25
|
+
* Returns a callable that builds validated `{ [msgName]: args }` envelopes.
|
|
26
|
+
* The schema is compiled once and cached — safe for batch usage.
|
|
27
|
+
*
|
|
28
|
+
* This follows the same pattern as `createTypedContract`: the schema type
|
|
29
|
+
* is resolved once at factory level, avoiding expensive repeated evaluation
|
|
30
|
+
* of `FromSchema` on complex schemas (12+ oneOf branches with $ref).
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* import { createMsgBuilder } from 'schemos/msg'
|
|
35
|
+
* import { cw20 } from 'schemos/schemas'
|
|
36
|
+
*
|
|
37
|
+
* const cw20Msg = createMsgBuilder(cw20.execute)
|
|
38
|
+
* const msg = cw20Msg('transfer', { amount: '1000', recipient: 'osmo1...' })
|
|
39
|
+
* // msg is typed as { transfer: { amount: string; recipient: string } }
|
|
40
|
+
*
|
|
41
|
+
* // Batch usage — schema compiled once, reused across calls:
|
|
42
|
+
* const msgs = [
|
|
43
|
+
* cw20Msg('transfer', { amount: '100', recipient: addr1 }),
|
|
44
|
+
* cw20Msg('transfer', { amount: '200', recipient: addr2 }),
|
|
45
|
+
* ]
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export function createMsgBuilder(schema) {
|
|
49
|
+
return ((msg, args, options) => {
|
|
50
|
+
return buildMsg(schema, msg, args, options);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
// TS2589 mitigation: factory isolates FromSchema to creation time, but MsgValidator
|
|
54
|
+
// exposes it directly as return type — tsc fully resolves it on declaration emit.
|
|
55
|
+
// Overload hides the impl behind `unknown`. MsgBuilder doesn't need this because
|
|
56
|
+
// its inner generic K (MessageNames/MessageArgs) defers resolution.
|
|
57
|
+
export function createMsgValidator(schema) {
|
|
58
|
+
return (data, options) => {
|
|
59
|
+
return validateMsg(schema, data, options);
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Validate data against a JSON Schema. Returns the data as-is if valid,
|
|
64
|
+
* throws a descriptive error if invalid.
|
|
65
|
+
*
|
|
66
|
+
* Reuses the same WeakMap-based validator cache as `buildMsg` — safe for
|
|
67
|
+
* repeated calls with the same schema reference.
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```ts
|
|
71
|
+
* import { validateMsg } from 'schemos'
|
|
72
|
+
*
|
|
73
|
+
* const initMsg = validateMsg(cw20InstantiateSchema, {
|
|
74
|
+
* name: 'Token', symbol: 'TKN', decimals: 6, initial_balances: []
|
|
75
|
+
* })
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export function validateMsg(schema, data, options) {
|
|
79
|
+
const { validate, ajv } = getValidator(schema);
|
|
80
|
+
if (!validate(data)) {
|
|
81
|
+
const prefix = options?.context ?? 'Validation failed';
|
|
82
|
+
throw new Error(`${prefix}: ${ajv.errorsText(validate.errors)}`);
|
|
83
|
+
}
|
|
84
|
+
return data;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Build a validated message envelope. Used internally by createMsgBuilder
|
|
88
|
+
* and createTypedContract. Accepts loose types — prefer createMsgBuilder
|
|
89
|
+
* for type-safe usage.
|
|
90
|
+
*/
|
|
91
|
+
export function buildMsg(schema, msg, args, options) {
|
|
92
|
+
const envelope = { [msg]: args };
|
|
93
|
+
const context = options?.context
|
|
94
|
+
? `${options.context} validation failed for "${msg}"`
|
|
95
|
+
: `Validation failed for "${msg}"`;
|
|
96
|
+
return validateMsg(schema, envelope, { context });
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=msg.js.map
|
package/dist/msg.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msg.js","sourceRoot":"","sources":["../src/msg.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAyB,MAAM,KAAK,CAAA;AAEhD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAuB9C,8EAA8E;AAC9E,iDAAiD;AACjD,8EAA8E;AAE9E,mFAAmF;AACnF,MAAM,cAAc,GAAG,IAAI,OAAO,EAG/B,CAAA;AAEH,SAAS,YAAY,CAAC,MAAkB;IAItC,MAAM,GAAG,GAAG,MAAgB,CAAA;IAC5B,IAAI,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IACpC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,GAAG,GAAG,IAAI,GAAG,EAAE,CAAA;QACrB,KAAK,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,EAAE,CAAC;YAC1D,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,CAAA;QAC1B,CAAC;QACD,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,MAAiC,CAAC,CAAA;QAC/D,MAAM,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAA;QAC1B,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAA;IACjC,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AASD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAe;IAEf,OAAO,CAAC,CAAC,GAAW,EAAE,IAAa,EAAE,OAA8B,EAAE,EAAE;QACrE,OAAO,QAAQ,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;IAC7C,CAAC,CAAoC,CAAA;AACvC,CAAC;AAgCD,oFAAoF;AACpF,kFAAkF;AAClF,iFAAiF;AACjF,oEAAoE;AACpE,MAAM,UAAU,kBAAkB,CAAC,MAAkB;IACnD,OAAO,CAAC,IAAa,EAAE,OAA8B,EAAE,EAAE;QACvD,OAAO,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,CAAA;IAC3C,CAAC,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,WAAW,CACzB,MAAkB,EAClB,IAAa,EACb,OAA8B;IAE9B,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;IAC9C,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;QACpB,MAAM,MAAM,GAAG,OAAO,EAAE,OAAO,IAAI,mBAAmB,CAAA;QACtD,MAAM,IAAI,KAAK,CAAC,GAAG,MAAM,KAAK,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IAClE,CAAC;IACD,OAAO,IAAS,CAAA;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,QAAQ,CACtB,MAAkB,EAClB,GAAW,EACX,IAAa,EACb,OAA8B;IAE9B,MAAM,QAAQ,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,CAAA;IAChC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO;QAC9B,CAAC,CAAC,GAAG,OAAO,CAAC,OAAO,2BAA2B,GAAG,GAAG;QACrD,CAAC,CAAC,0BAA0B,GAAG,GAAG,CAAA;IACpC,OAAO,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,CAAA;AACnD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msg.test-d.d.ts","sourceRoot":"","sources":["../src/msg.test-d.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { assertType, expectTypeOf, test } from 'vitest';
|
|
2
|
+
import { createMsgBuilder, createMsgValidator } from './msg.js';
|
|
3
|
+
import { cw20ExecuteSchema, cw20InstantiateSchema, cw20QuerySchema, } from './schemas/cw20/index.js';
|
|
4
|
+
test('InferMsg produces same type as FromSchema', () => {
|
|
5
|
+
expectTypeOf().toEqualTypeOf();
|
|
6
|
+
expectTypeOf().toEqualTypeOf();
|
|
7
|
+
});
|
|
8
|
+
test('InferMsg<execute> accepts valid messages', () => {
|
|
9
|
+
assertType({
|
|
10
|
+
transfer: { amount: '1000', recipient: 'osmo1abc' },
|
|
11
|
+
});
|
|
12
|
+
assertType({ burn: { amount: '500' } });
|
|
13
|
+
assertType({
|
|
14
|
+
send: { amount: '100', contract: 'osmo1xyz', msg: 'base64' },
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
test('InferMsg<query> accepts valid messages', () => {
|
|
18
|
+
assertType({ balance: { address: 'osmo1abc' } });
|
|
19
|
+
assertType({ token_info: {} });
|
|
20
|
+
});
|
|
21
|
+
test('MessageNames extracts execute message names', () => {
|
|
22
|
+
assertType('transfer');
|
|
23
|
+
assertType('burn');
|
|
24
|
+
assertType('send');
|
|
25
|
+
assertType('mint');
|
|
26
|
+
assertType('increase_allowance');
|
|
27
|
+
assertType('decrease_allowance');
|
|
28
|
+
assertType('transfer_from');
|
|
29
|
+
assertType('send_from');
|
|
30
|
+
assertType('burn_from');
|
|
31
|
+
});
|
|
32
|
+
test('MessageNames extracts query message names', () => {
|
|
33
|
+
assertType('balance');
|
|
34
|
+
assertType('token_info');
|
|
35
|
+
assertType('allowance');
|
|
36
|
+
assertType('all_allowances');
|
|
37
|
+
assertType('all_accounts');
|
|
38
|
+
});
|
|
39
|
+
test('MessageNames rejects invalid names', () => {
|
|
40
|
+
// @ts-expect-error - 'xfer' is not a valid execute message name
|
|
41
|
+
assertType('xfer');
|
|
42
|
+
// @ts-expect-error - 'balances' is not a valid query name
|
|
43
|
+
assertType('balances');
|
|
44
|
+
});
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// MessageArgs: narrow args for a specific message name
|
|
47
|
+
// ---------------------------------------------------------------------------
|
|
48
|
+
test('MessageArgs narrows transfer to { amount, recipient }', () => {
|
|
49
|
+
expectTypeOf().toEqualTypeOf();
|
|
50
|
+
});
|
|
51
|
+
test('MessageArgs narrows burn to { amount }', () => {
|
|
52
|
+
expectTypeOf().toEqualTypeOf();
|
|
53
|
+
});
|
|
54
|
+
test('MessageArgs narrows balance query to { address }', () => {
|
|
55
|
+
expectTypeOf().toEqualTypeOf();
|
|
56
|
+
});
|
|
57
|
+
test('MessageArgs narrows token_info query to {}', () => {
|
|
58
|
+
expectTypeOf().toEqualTypeOf();
|
|
59
|
+
});
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
// InferResponse: extract typed response from responses schema map
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
test('InferResponse infers balance response', () => {
|
|
64
|
+
expectTypeOf().toEqualTypeOf();
|
|
65
|
+
});
|
|
66
|
+
test('InferResponse infers token_info response', () => {
|
|
67
|
+
expectTypeOf().toHaveProperty('name');
|
|
68
|
+
expectTypeOf().toHaveProperty('symbol');
|
|
69
|
+
expectTypeOf().toHaveProperty('decimals');
|
|
70
|
+
expectTypeOf().toHaveProperty('total_supply');
|
|
71
|
+
});
|
|
72
|
+
test('InferResponse rejects invalid response key', () => {
|
|
73
|
+
});
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// createMsgBuilder: return type narrowing (Level 2 type tests)
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
const cw20Msg = createMsgBuilder(cw20ExecuteSchema);
|
|
78
|
+
const cw20QueryMsg = createMsgBuilder(cw20QuerySchema);
|
|
79
|
+
test('createMsgBuilder return type narrows to single-key envelope', () => {
|
|
80
|
+
const result = cw20Msg('transfer', {
|
|
81
|
+
amount: '1000',
|
|
82
|
+
recipient: 'osmo1abc',
|
|
83
|
+
});
|
|
84
|
+
expectTypeOf(result).toEqualTypeOf();
|
|
85
|
+
});
|
|
86
|
+
test('createMsgBuilder return type is NOT the full union', () => {
|
|
87
|
+
const result = cw20Msg('transfer', {
|
|
88
|
+
amount: '1000',
|
|
89
|
+
recipient: 'osmo1abc',
|
|
90
|
+
});
|
|
91
|
+
expectTypeOf(result).not.toEqualTypeOf();
|
|
92
|
+
});
|
|
93
|
+
test('createMsgBuilder narrows query envelope too', () => {
|
|
94
|
+
const result = cw20QueryMsg('balance', { address: 'osmo1abc' });
|
|
95
|
+
expectTypeOf(result).toEqualTypeOf();
|
|
96
|
+
});
|
|
97
|
+
test('createMsgBuilder rejects invalid message name at type level', () => {
|
|
98
|
+
expectTypeOf(cw20Msg).parameter(0).not.toExtend();
|
|
99
|
+
});
|
|
100
|
+
test('createMsgBuilder rejects wrong args shape at type level', () => {
|
|
101
|
+
// Missing 'recipient' — should not be assignable to transfer args
|
|
102
|
+
expectTypeOf().not.toExtend();
|
|
103
|
+
});
|
|
104
|
+
test('createMsgBuilder rejects typo in field name at type level', () => {
|
|
105
|
+
// 'recipent' is a typo — should not be assignable
|
|
106
|
+
expectTypeOf().not.toExtend();
|
|
107
|
+
});
|
|
108
|
+
// ---------------------------------------------------------------------------
|
|
109
|
+
// createMsgValidator: factory-level type inference
|
|
110
|
+
// ---------------------------------------------------------------------------
|
|
111
|
+
test('createMsgValidator infers instantiate struct properties', () => {
|
|
112
|
+
const validateInit = createMsgValidator(cw20InstantiateSchema);
|
|
113
|
+
expectTypeOf().toHaveProperty('name');
|
|
114
|
+
expectTypeOf().toHaveProperty('symbol');
|
|
115
|
+
expectTypeOf().toHaveProperty('decimals');
|
|
116
|
+
});
|
|
117
|
+
test('createMsgValidator infers execute msg union', () => {
|
|
118
|
+
const validateExec = createMsgValidator(cw20ExecuteSchema);
|
|
119
|
+
expectTypeOf().toEqualTypeOf();
|
|
120
|
+
});
|
|
121
|
+
//# sourceMappingURL=msg.test-d.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msg.test-d.js","sourceRoot":"","sources":["../src/msg.test-d.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msg.test.d.ts","sourceRoot":"","sources":["../src/msg.test.ts"],"names":[],"mappings":""}
|
package/dist/msg.test.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { Ajv } from 'ajv';
|
|
2
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
3
|
+
import { buildMsg, createMsgBuilder, createMsgValidator, validateMsg, } from './msg.js';
|
|
4
|
+
import { cw20ExecuteSchema, cw20InstantiateSchema, cw20QuerySchema, } from './schemas/cw20/index.js';
|
|
5
|
+
describe('createMsgBuilder', () => {
|
|
6
|
+
const cw20Msg = createMsgBuilder(cw20ExecuteSchema);
|
|
7
|
+
const cw20QueryMsg = createMsgBuilder(cw20QuerySchema);
|
|
8
|
+
test('returns correct envelope for valid execute message', () => {
|
|
9
|
+
const result = cw20Msg('transfer', {
|
|
10
|
+
amount: '1000',
|
|
11
|
+
recipient: 'osmo1abc',
|
|
12
|
+
});
|
|
13
|
+
expect(result).toEqual({
|
|
14
|
+
transfer: { amount: '1000', recipient: 'osmo1abc' },
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
test('returns correct envelope for burn', () => {
|
|
18
|
+
const result = cw20Msg('burn', { amount: '500' });
|
|
19
|
+
expect(result).toEqual({ burn: { amount: '500' } });
|
|
20
|
+
});
|
|
21
|
+
test('works with query schema', () => {
|
|
22
|
+
const result = cw20QueryMsg('balance', { address: 'osmo1abc' });
|
|
23
|
+
expect(result).toEqual({ balance: { address: 'osmo1abc' } });
|
|
24
|
+
});
|
|
25
|
+
test('works with query schema (empty args)', () => {
|
|
26
|
+
const result = cw20QueryMsg('token_info', {});
|
|
27
|
+
expect(result).toEqual({ token_info: {} });
|
|
28
|
+
});
|
|
29
|
+
test('throws on missing required field', () => {
|
|
30
|
+
expect(() => cw20Msg('transfer',
|
|
31
|
+
// @ts-expect-error - testing runtime: missing recipient
|
|
32
|
+
{ amount: '1000' })).toThrow('Validation failed for "transfer"');
|
|
33
|
+
});
|
|
34
|
+
test('throws on wrong type (number instead of string for Uint128)', () => {
|
|
35
|
+
expect(() => cw20Msg('transfer',
|
|
36
|
+
// @ts-expect-error - testing runtime: amount should be string
|
|
37
|
+
{ amount: 1000, recipient: 'osmo1abc' })).toThrow('Validation failed for "transfer"');
|
|
38
|
+
});
|
|
39
|
+
test('throws on additional properties', () => {
|
|
40
|
+
expect(() => cw20Msg('burn',
|
|
41
|
+
// @ts-expect-error - testing runtime: extra field
|
|
42
|
+
{ amount: '500', extraField: true })).toThrow('Validation failed for "burn"');
|
|
43
|
+
});
|
|
44
|
+
test('context option prefixes error message', () => {
|
|
45
|
+
const cw20Execute = createMsgBuilder(cw20ExecuteSchema);
|
|
46
|
+
expect(() => cw20Execute('transfer',
|
|
47
|
+
// @ts-expect-error - testing runtime: missing recipient
|
|
48
|
+
{ amount: '1000' }, { context: 'Execute' })).toThrow('Execute validation failed for "transfer"');
|
|
49
|
+
});
|
|
50
|
+
test('context option for query', () => {
|
|
51
|
+
const cw20Query = createMsgBuilder(cw20QuerySchema);
|
|
52
|
+
expect(() => cw20Query('balance',
|
|
53
|
+
// @ts-expect-error - testing runtime: missing address
|
|
54
|
+
{}, { context: 'Query' })).toThrow('Query validation failed for "balance"');
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
describe('validateMsg', () => {
|
|
58
|
+
// A simple flat struct schema — typical for instantiate messages
|
|
59
|
+
const instantiateSchema = {
|
|
60
|
+
type: 'object',
|
|
61
|
+
required: ['name', 'symbol', 'decimals', 'initial_balances'],
|
|
62
|
+
additionalProperties: false,
|
|
63
|
+
properties: {
|
|
64
|
+
name: { type: 'string' },
|
|
65
|
+
symbol: { type: 'string' },
|
|
66
|
+
decimals: { type: 'integer' },
|
|
67
|
+
initial_balances: { type: 'array', items: { type: 'object' } },
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
test('returns data as-is when valid', () => {
|
|
71
|
+
const data = {
|
|
72
|
+
name: 'Token',
|
|
73
|
+
symbol: 'TKN',
|
|
74
|
+
decimals: 6,
|
|
75
|
+
initial_balances: [],
|
|
76
|
+
};
|
|
77
|
+
const result = validateMsg(instantiateSchema, data);
|
|
78
|
+
expect(result).toBe(data);
|
|
79
|
+
});
|
|
80
|
+
test('throws when required field is missing', () => {
|
|
81
|
+
expect(() => validateMsg(instantiateSchema, { name: 'Token', symbol: 'TKN' })).toThrow('Validation failed:');
|
|
82
|
+
});
|
|
83
|
+
test('throws when field has wrong type', () => {
|
|
84
|
+
expect(() => validateMsg(instantiateSchema, {
|
|
85
|
+
name: 'Token',
|
|
86
|
+
symbol: 'TKN',
|
|
87
|
+
decimals: 'six',
|
|
88
|
+
initial_balances: [],
|
|
89
|
+
})).toThrow('Validation failed:');
|
|
90
|
+
});
|
|
91
|
+
test('context option prefixes error message', () => {
|
|
92
|
+
expect(() => validateMsg(instantiateSchema, { name: 'Token' }, { context: 'Instantiate' })).toThrow('Instantiate:');
|
|
93
|
+
});
|
|
94
|
+
test('works for flat struct schema (instantiate use case)', () => {
|
|
95
|
+
const result = validateMsg(instantiateSchema, {
|
|
96
|
+
name: 'Token',
|
|
97
|
+
symbol: 'TKN',
|
|
98
|
+
decimals: 6,
|
|
99
|
+
initial_balances: [],
|
|
100
|
+
});
|
|
101
|
+
expect(result.name).toBe('Token');
|
|
102
|
+
expect(result.decimals).toBe(6);
|
|
103
|
+
});
|
|
104
|
+
test('reuses validator cache for same schema reference', () => {
|
|
105
|
+
const compileSpy = vi.spyOn(Ajv.prototype, 'compile');
|
|
106
|
+
validateMsg(instantiateSchema, {
|
|
107
|
+
name: 'A',
|
|
108
|
+
symbol: 'A',
|
|
109
|
+
decimals: 0,
|
|
110
|
+
initial_balances: [],
|
|
111
|
+
});
|
|
112
|
+
const firstCallCount = compileSpy.mock.calls.length;
|
|
113
|
+
validateMsg(instantiateSchema, {
|
|
114
|
+
name: 'B',
|
|
115
|
+
symbol: 'B',
|
|
116
|
+
decimals: 0,
|
|
117
|
+
initial_balances: [],
|
|
118
|
+
});
|
|
119
|
+
expect(compileSpy.mock.calls.length).toBe(firstCallCount);
|
|
120
|
+
compileSpy.mockRestore();
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
describe('buildMsg Ajv caching', () => {
|
|
124
|
+
test('reuses compiled validator for same schema reference', () => {
|
|
125
|
+
const compileSpy = vi.spyOn(Ajv.prototype, 'compile');
|
|
126
|
+
// First call compiles the schema
|
|
127
|
+
buildMsg(cw20ExecuteSchema, 'transfer', {
|
|
128
|
+
amount: '1',
|
|
129
|
+
recipient: 'osmo1abc',
|
|
130
|
+
});
|
|
131
|
+
const firstCallCount = compileSpy.mock.calls.length;
|
|
132
|
+
// Second call should reuse cached validator
|
|
133
|
+
buildMsg(cw20ExecuteSchema, 'burn', { amount: '1' });
|
|
134
|
+
expect(compileSpy.mock.calls.length).toBe(firstCallCount);
|
|
135
|
+
compileSpy.mockRestore();
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
describe('createMsgValidator', () => {
|
|
139
|
+
const validateInit = createMsgValidator(cw20InstantiateSchema);
|
|
140
|
+
test('returns data as-is when valid', () => {
|
|
141
|
+
const result = validateInit({
|
|
142
|
+
name: 'Token',
|
|
143
|
+
symbol: 'TKN',
|
|
144
|
+
decimals: 6,
|
|
145
|
+
initial_balances: [],
|
|
146
|
+
});
|
|
147
|
+
expect(result.name).toBe('Token');
|
|
148
|
+
expect(result.decimals).toBe(6);
|
|
149
|
+
});
|
|
150
|
+
test('throws when required field is missing', () => {
|
|
151
|
+
// @ts-expect-error — intentionally missing required fields for runtime test
|
|
152
|
+
expect(() => validateInit({ name: 'Token', symbol: 'TKN' })).toThrow('Validation failed:');
|
|
153
|
+
});
|
|
154
|
+
test('throws when field has wrong type', () => {
|
|
155
|
+
expect(() => validateInit({
|
|
156
|
+
name: 'Token',
|
|
157
|
+
symbol: 'TKN',
|
|
158
|
+
// @ts-expect-error — intentionally wrong type for runtime test
|
|
159
|
+
decimals: 'six',
|
|
160
|
+
initial_balances: [],
|
|
161
|
+
})).toThrow('Validation failed:');
|
|
162
|
+
});
|
|
163
|
+
test('context option prefixes error message', () => {
|
|
164
|
+
expect(() =>
|
|
165
|
+
// @ts-expect-error — intentionally missing required fields for runtime test
|
|
166
|
+
validateInit({ name: 'Token' }, { context: 'Instantiate' })).toThrow('Instantiate:');
|
|
167
|
+
});
|
|
168
|
+
test('reuses validator cache across calls', () => {
|
|
169
|
+
const compileSpy = vi.spyOn(Ajv.prototype, 'compile');
|
|
170
|
+
validateInit({ name: 'A', symbol: 'A', decimals: 0, initial_balances: [] });
|
|
171
|
+
const firstCallCount = compileSpy.mock.calls.length;
|
|
172
|
+
validateInit({ name: 'B', symbol: 'B', decimals: 0, initial_balances: [] });
|
|
173
|
+
expect(compileSpy.mock.calls.length).toBe(firstCallCount);
|
|
174
|
+
compileSpy.mockRestore();
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
//# sourceMappingURL=msg.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"msg.test.js","sourceRoot":"","sources":["../src/msg.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixed-tuple.test-d.d.ts","sourceRoot":"","sources":["../../src/patches/fixed-tuple.test-d.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { expectTypeOf, test } from 'vitest';
|
|
2
|
+
// ---------------------------------------------------------------------------
|
|
3
|
+
// Fixed-length array patch: minItems === maxItems should produce a tuple type
|
|
4
|
+
// Mirrors ThomasAribart/json-schema-to-ts#231
|
|
5
|
+
// ---------------------------------------------------------------------------
|
|
6
|
+
// -- AssetInfo (native or cw20 token) ---------------------------------------
|
|
7
|
+
const assetInfoSchema = {
|
|
8
|
+
oneOf: [
|
|
9
|
+
{
|
|
10
|
+
type: 'object',
|
|
11
|
+
required: ['native'],
|
|
12
|
+
properties: { native: { type: 'string' } },
|
|
13
|
+
additionalProperties: false,
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
type: 'object',
|
|
17
|
+
required: ['cw20'],
|
|
18
|
+
properties: { cw20: { type: 'string' } },
|
|
19
|
+
additionalProperties: false,
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
};
|
|
23
|
+
// -- DEX Pair: exactly 2 AssetInfo ------------------------------------------
|
|
24
|
+
const pairSchema = {
|
|
25
|
+
type: 'object',
|
|
26
|
+
required: ['asset_infos', 'contract_addr'],
|
|
27
|
+
properties: {
|
|
28
|
+
asset_infos: {
|
|
29
|
+
type: 'array',
|
|
30
|
+
items: assetInfoSchema,
|
|
31
|
+
minItems: 2,
|
|
32
|
+
maxItems: 2,
|
|
33
|
+
},
|
|
34
|
+
contract_addr: { type: 'string' },
|
|
35
|
+
},
|
|
36
|
+
additionalProperties: false,
|
|
37
|
+
};
|
|
38
|
+
test('Pair.asset_infos is a fixed-length tuple [AssetInfo, AssetInfo]', () => {
|
|
39
|
+
expectTypeOf().toEqualTypeOf();
|
|
40
|
+
});
|
|
41
|
+
// -- Empty fixed-length array (minItems === maxItems === 0) -----------------
|
|
42
|
+
const emptyArraySchema = {
|
|
43
|
+
type: 'object',
|
|
44
|
+
required: ['items'],
|
|
45
|
+
properties: {
|
|
46
|
+
items: {
|
|
47
|
+
type: 'array',
|
|
48
|
+
items: { type: 'string' },
|
|
49
|
+
minItems: 0,
|
|
50
|
+
maxItems: 0,
|
|
51
|
+
},
|
|
52
|
+
},
|
|
53
|
+
additionalProperties: false,
|
|
54
|
+
};
|
|
55
|
+
test('empty fixed-length array is []', () => {
|
|
56
|
+
expectTypeOf().toEqualTypeOf();
|
|
57
|
+
});
|
|
58
|
+
// -- Range array (minItems !== maxItems) should still be T[] ----------------
|
|
59
|
+
const rangeArraySchema = {
|
|
60
|
+
type: 'object',
|
|
61
|
+
required: ['items'],
|
|
62
|
+
properties: {
|
|
63
|
+
items: {
|
|
64
|
+
type: 'array',
|
|
65
|
+
items: { type: 'number' },
|
|
66
|
+
minItems: 1,
|
|
67
|
+
maxItems: 3,
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
additionalProperties: false,
|
|
71
|
+
};
|
|
72
|
+
// TODO: Update this once json-schema-to-ts supports range arrays as tuples (minItems !== maxItems)
|
|
73
|
+
test('range array (min !== max) stays as T[]', () => {
|
|
74
|
+
expectTypeOf().toEqualTypeOf();
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=fixed-tuple.test-d.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fixed-tuple.test-d.js","sourceRoot":"","sources":["../../src/patches/fixed-tuple.test-d.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAE3C,8EAA8E;AAC9E,8EAA8E;AAC9E,8CAA8C;AAC9C,8EAA8E;AAE9E,8EAA8E;AAC9E,MAAM,eAAe,GAAG;IACtB,KAAK,EAAE;QACL;YACE,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,CAAC,QAAQ,CAAC;YACpB,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;YAC1C,oBAAoB,EAAE,KAAK;SAC5B;QACD;YACE,IAAI,EAAE,QAAQ;YACd,QAAQ,EAAE,CAAC,MAAM,CAAC;YAClB,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;YACxC,oBAAoB,EAAE,KAAK;SAC5B;KACF;CACO,CAAA;AAIV,8EAA8E;AAC9E,MAAM,UAAU,GAAG;IACjB,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,CAAC,aAAa,EAAE,eAAe,CAAC;IAC1C,UAAU,EAAE;QACV,WAAW,EAAE;YACX,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,eAAe;YACtB,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,CAAC;SACZ;QACD,aAAa,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KAClC;IACD,oBAAoB,EAAE,KAAK;CACnB,CAAA;AAIV,IAAI,CAAC,iEAAiE,EAAE,GAAG,EAAE;IAC3E,YAAY,EAAuB,CAAC,aAAa,EAA0B,CAAA;AAC7E,CAAC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,MAAM,gBAAgB,GAAG;IACvB,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,CAAC,OAAO,CAAC;IACnB,UAAU,EAAE;QACV,KAAK,EAAE;YACL,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACzB,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,CAAC;SACZ;KACF;IACD,oBAAoB,EAAE,KAAK;CACnB,CAAA;AAIV,IAAI,CAAC,gCAAgC,EAAE,GAAG,EAAE;IAC1C,YAAY,EAAuB,CAAC,aAAa,EAAM,CAAA;AACzD,CAAC,CAAC,CAAA;AAEF,8EAA8E;AAC9E,MAAM,gBAAgB,GAAG;IACvB,IAAI,EAAE,QAAQ;IACd,QAAQ,EAAE,CAAC,OAAO,CAAC;IACnB,UAAU,EAAE;QACV,KAAK,EAAE;YACL,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YACzB,QAAQ,EAAE,CAAC;YACX,QAAQ,EAAE,CAAC;SACZ;KACF;IACD,oBAAoB,EAAE,KAAK;CACnB,CAAA;AAIV,mGAAmG;AACnG,IAAI,CAAC,wCAAwC,EAAE,GAAG,EAAE;IAClD,YAAY,EAAuB,CAAC,aAAa,EAAY,CAAA;AAC/D,CAAC,CAAC,CAAA"}
|