@thyme-sh/sdk 0.2.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/README.md +256 -0
- package/dist/index.d.ts +310 -0
- package/dist/index.js +78 -0
- package/dist/index.js.map +1 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# @thyme-sh/sdk
|
|
2
|
+
|
|
3
|
+
SDK for authoring Web3 automation tasks with Thyme.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @thyme-sh/sdk zod viem
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Create a task with embedded schema:
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { defineTask, z } from '@thyme-sh/sdk'
|
|
17
|
+
import { encodeFunctionData } from 'viem'
|
|
18
|
+
|
|
19
|
+
const abi = [
|
|
20
|
+
{
|
|
21
|
+
name: 'updatePrice',
|
|
22
|
+
type: 'function',
|
|
23
|
+
stateMutability: 'nonpayable',
|
|
24
|
+
inputs: [{ name: 'price', type: 'uint256' }],
|
|
25
|
+
outputs: [],
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
name: 'getPrice',
|
|
29
|
+
type: 'function',
|
|
30
|
+
stateMutability: 'view',
|
|
31
|
+
inputs: [],
|
|
32
|
+
outputs: [{ type: 'uint256' }],
|
|
33
|
+
},
|
|
34
|
+
] as const
|
|
35
|
+
|
|
36
|
+
export default defineTask({
|
|
37
|
+
// Define your arguments schema with type-safe Ethereum addresses
|
|
38
|
+
schema: z.object({
|
|
39
|
+
oracleAddress: z.address(), // Validates and returns viem's Address type
|
|
40
|
+
threshold: z.number().min(0),
|
|
41
|
+
}),
|
|
42
|
+
|
|
43
|
+
// Main execution logic
|
|
44
|
+
async run(ctx) {
|
|
45
|
+
const { oracleAddress, threshold } = ctx.args
|
|
46
|
+
|
|
47
|
+
// Read from blockchain using the public client
|
|
48
|
+
const lastPrice = await ctx.client.readContract({
|
|
49
|
+
address: oracleAddress,
|
|
50
|
+
abi,
|
|
51
|
+
functionName: 'getPrice',
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
// Your logic here
|
|
55
|
+
const price = await fetchPrice()
|
|
56
|
+
|
|
57
|
+
if (price > threshold && price !== lastPrice) {
|
|
58
|
+
return {
|
|
59
|
+
canExec: true,
|
|
60
|
+
calls: [{
|
|
61
|
+
to: oracleAddress,
|
|
62
|
+
data: encodeFunctionData({
|
|
63
|
+
abi,
|
|
64
|
+
functionName: 'updatePrice',
|
|
65
|
+
args: [price],
|
|
66
|
+
}),
|
|
67
|
+
}]
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return {
|
|
72
|
+
canExec: false,
|
|
73
|
+
message: 'Price below threshold or unchanged'
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
// Optional: Handle successful execution
|
|
78
|
+
async onSuccess(ctx, txHashes) {
|
|
79
|
+
console.log('Executed:', txHashes)
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
// Optional: Handle failed execution
|
|
83
|
+
async onFail(ctx, error) {
|
|
84
|
+
console.error('Failed:', error.message)
|
|
85
|
+
},
|
|
86
|
+
})
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Schema Validation
|
|
90
|
+
|
|
91
|
+
The SDK provides an extended Zod instance with Ethereum-specific validators:
|
|
92
|
+
|
|
93
|
+
### `z.address()`
|
|
94
|
+
|
|
95
|
+
Validates an Ethereum address and returns viem's `Address` type:
|
|
96
|
+
|
|
97
|
+
```typescript
|
|
98
|
+
import { defineTask, z } from '@thyme-sh/sdk'
|
|
99
|
+
|
|
100
|
+
export default defineTask({
|
|
101
|
+
schema: z.object({
|
|
102
|
+
targetAddress: z.address(), // Validates checksum and format
|
|
103
|
+
}),
|
|
104
|
+
async run(ctx) {
|
|
105
|
+
// ctx.args.targetAddress is typed as Address from viem
|
|
106
|
+
return {
|
|
107
|
+
canExec: true,
|
|
108
|
+
calls: [{
|
|
109
|
+
to: ctx.args.targetAddress,
|
|
110
|
+
data: '0x',
|
|
111
|
+
}]
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
})
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
You can also use standard Zod validators:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
schema: z.object({
|
|
121
|
+
address: z.address(),
|
|
122
|
+
amount: z.bigint().positive(),
|
|
123
|
+
enabled: z.boolean(),
|
|
124
|
+
metadata: z.string().optional(),
|
|
125
|
+
})
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Public Client
|
|
129
|
+
|
|
130
|
+
The context includes a viem `PublicClient` for reading blockchain data:
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
import { defineTask, z } from '@thyme-sh/sdk'
|
|
134
|
+
|
|
135
|
+
export default defineTask({
|
|
136
|
+
schema: z.object({
|
|
137
|
+
tokenAddress: z.address(),
|
|
138
|
+
threshold: z.bigint(),
|
|
139
|
+
}),
|
|
140
|
+
|
|
141
|
+
async run(ctx) {
|
|
142
|
+
// Read contract state
|
|
143
|
+
const totalSupply = await ctx.client.readContract({
|
|
144
|
+
address: ctx.args.tokenAddress,
|
|
145
|
+
abi: [{
|
|
146
|
+
name: 'totalSupply',
|
|
147
|
+
type: 'function',
|
|
148
|
+
stateMutability: 'view',
|
|
149
|
+
inputs: [],
|
|
150
|
+
outputs: [{ type: 'uint256' }],
|
|
151
|
+
}],
|
|
152
|
+
functionName: 'totalSupply',
|
|
153
|
+
})
|
|
154
|
+
|
|
155
|
+
// Get block data
|
|
156
|
+
const blockNumber = await ctx.client.getBlockNumber()
|
|
157
|
+
const block = await ctx.client.getBlock({ blockNumber })
|
|
158
|
+
|
|
159
|
+
// Get balance
|
|
160
|
+
const balance = await ctx.client.getBalance({
|
|
161
|
+
address: ctx.args.tokenAddress,
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
if (totalSupply > ctx.args.threshold) {
|
|
165
|
+
return {
|
|
166
|
+
canExec: true,
|
|
167
|
+
calls: [...]
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
canExec: false,
|
|
173
|
+
message: 'Threshold not met'
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
})
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
The client is configured using the `RPC_URL` environment variable in your `.env` file.
|
|
180
|
+
|
|
181
|
+
## Encoding Function Calls
|
|
182
|
+
|
|
183
|
+
Use viem's `encodeFunctionData` to encode function calls:
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { defineTask, z } from '@thyme-sh/sdk'
|
|
187
|
+
import { encodeFunctionData } from 'viem'
|
|
188
|
+
|
|
189
|
+
const abi = [
|
|
190
|
+
'function transfer(address to, uint256 amount) returns (bool)',
|
|
191
|
+
] as const
|
|
192
|
+
|
|
193
|
+
export default defineTask({
|
|
194
|
+
schema: z.object({
|
|
195
|
+
token: z.address(),
|
|
196
|
+
recipient: z.address(),
|
|
197
|
+
}),
|
|
198
|
+
|
|
199
|
+
async run(ctx) {
|
|
200
|
+
return {
|
|
201
|
+
canExec: true,
|
|
202
|
+
calls: [{
|
|
203
|
+
to: ctx.args.token,
|
|
204
|
+
data: encodeFunctionData({
|
|
205
|
+
abi,
|
|
206
|
+
functionName: 'transfer',
|
|
207
|
+
args: [ctx.args.recipient, 1000n],
|
|
208
|
+
}),
|
|
209
|
+
}]
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
})
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Viem's `encodeFunctionData` provides full type safety and validation.
|
|
216
|
+
|
|
217
|
+
## API
|
|
218
|
+
|
|
219
|
+
### `defineTask(definition)`
|
|
220
|
+
|
|
221
|
+
Define a Web3 automation task.
|
|
222
|
+
|
|
223
|
+
#### Parameters
|
|
224
|
+
|
|
225
|
+
- `definition.schema` - Zod schema for validating task arguments
|
|
226
|
+
- `definition.run` - Main execution function that returns whether to execute and what calls to make
|
|
227
|
+
- `definition.onSuccess` - Optional callback on successful execution
|
|
228
|
+
- `definition.onFail` - Optional callback on failed execution
|
|
229
|
+
|
|
230
|
+
#### Returns
|
|
231
|
+
|
|
232
|
+
The task definition (for type inference).
|
|
233
|
+
|
|
234
|
+
## Types
|
|
235
|
+
|
|
236
|
+
### `ThymeContext<TArgs>`
|
|
237
|
+
|
|
238
|
+
Context provided to task execution:
|
|
239
|
+
- `args` - User-provided arguments validated against schema
|
|
240
|
+
- `client` - Viem public client for reading blockchain data
|
|
241
|
+
|
|
242
|
+
### `TaskResult`
|
|
243
|
+
|
|
244
|
+
Result from task execution:
|
|
245
|
+
- `{ canExec: true, calls: Call[] }` - Execute these calls
|
|
246
|
+
- `{ canExec: false, message: string }` - Don't execute, with reason
|
|
247
|
+
|
|
248
|
+
### `Call`
|
|
249
|
+
|
|
250
|
+
A call to execute on-chain:
|
|
251
|
+
- `to` - Target contract address
|
|
252
|
+
- `data` - Encoded function call data
|
|
253
|
+
|
|
254
|
+
## License
|
|
255
|
+
|
|
256
|
+
MIT
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { PublicClient, Address, Hex } from 'viem';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Context provided to task execution
|
|
6
|
+
*/
|
|
7
|
+
interface ThymeContext<TArgs> {
|
|
8
|
+
/** User-provided arguments validated against schema */
|
|
9
|
+
args: TArgs;
|
|
10
|
+
/** Viem public client for reading blockchain data */
|
|
11
|
+
client: PublicClient;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* A call to be executed on-chain
|
|
15
|
+
*/
|
|
16
|
+
interface Call {
|
|
17
|
+
/** Target contract address */
|
|
18
|
+
to: Address;
|
|
19
|
+
/** Encoded function call data */
|
|
20
|
+
data: Hex;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Result when task determines execution should proceed
|
|
24
|
+
*/
|
|
25
|
+
interface SuccessResult {
|
|
26
|
+
canExec: true;
|
|
27
|
+
/** Array of calls to execute on-chain */
|
|
28
|
+
calls: Call[];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Result when task determines execution should not proceed
|
|
32
|
+
*/
|
|
33
|
+
interface FailResult {
|
|
34
|
+
canExec: false;
|
|
35
|
+
/** Reason why execution should not proceed */
|
|
36
|
+
message: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Result returned from task execution
|
|
40
|
+
*/
|
|
41
|
+
type TaskResult = SuccessResult | FailResult;
|
|
42
|
+
/**
|
|
43
|
+
* Task definition with schema and execution logic
|
|
44
|
+
*/
|
|
45
|
+
interface TaskDefinition<TSchema extends z.ZodType> {
|
|
46
|
+
/** Zod schema for validating task arguments */
|
|
47
|
+
schema: TSchema;
|
|
48
|
+
/** Main execution function */
|
|
49
|
+
run: (ctx: ThymeContext<z.infer<TSchema>>) => Promise<TaskResult>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Define a Web3 automation task
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* import { defineTask, z } from '@thyme-sh/sdk'
|
|
58
|
+
* import { encodeFunctionData } from 'viem'
|
|
59
|
+
*
|
|
60
|
+
* const abi = [
|
|
61
|
+
* 'function transfer(address to, uint256 amount) returns (bool)',
|
|
62
|
+
* ] as const
|
|
63
|
+
*
|
|
64
|
+
* export default defineTask({
|
|
65
|
+
* schema: z.object({
|
|
66
|
+
* targetAddress: z.address(),
|
|
67
|
+
* }),
|
|
68
|
+
* async run(ctx) {
|
|
69
|
+
* return {
|
|
70
|
+
* canExec: true,
|
|
71
|
+
* calls: [{
|
|
72
|
+
* to: ctx.args.targetAddress,
|
|
73
|
+
* data: encodeFunctionData({
|
|
74
|
+
* abi,
|
|
75
|
+
* functionName: 'transfer',
|
|
76
|
+
* args: [recipientAddress, 1000n],
|
|
77
|
+
* }),
|
|
78
|
+
* }]
|
|
79
|
+
* }
|
|
80
|
+
* }
|
|
81
|
+
* })
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
declare function defineTask<TSchema extends z.ZodType>(definition: TaskDefinition<TSchema>): TaskDefinition<TSchema>;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Extended Zod with Ethereum address validation
|
|
88
|
+
*/
|
|
89
|
+
declare const zodExtended: {
|
|
90
|
+
/**
|
|
91
|
+
* Validates an Ethereum address and returns viem's Address type
|
|
92
|
+
* Accepts both checksummed and non-checksummed addresses
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```typescript
|
|
96
|
+
* import { zodExtended as z } from '@thyme-sh/sdk'
|
|
97
|
+
*
|
|
98
|
+
* const schema = z.object({
|
|
99
|
+
* targetAddress: z.address(),
|
|
100
|
+
* })
|
|
101
|
+
* ```
|
|
102
|
+
*/
|
|
103
|
+
address: () => z.ZodEffects<z.ZodEffects<z.ZodString, `0x${string}`, string>, `0x${string}`, string>;
|
|
104
|
+
setErrorMap(map: z.ZodErrorMap): void;
|
|
105
|
+
getErrorMap(): z.ZodErrorMap;
|
|
106
|
+
defaultErrorMap: z.ZodErrorMap;
|
|
107
|
+
addIssueToContext(ctx: z.ParseContext, issueData: z.IssueData): void;
|
|
108
|
+
makeIssue: (params: {
|
|
109
|
+
data: any;
|
|
110
|
+
path: (string | number)[];
|
|
111
|
+
errorMaps: z.ZodErrorMap[];
|
|
112
|
+
issueData: z.IssueData;
|
|
113
|
+
}) => z.ZodIssue;
|
|
114
|
+
EMPTY_PATH: z.ParsePath;
|
|
115
|
+
ParseStatus: typeof z.ParseStatus;
|
|
116
|
+
INVALID: z.INVALID;
|
|
117
|
+
DIRTY: <T>(value: T) => z.DIRTY<T>;
|
|
118
|
+
OK: <T>(value: T) => z.OK<T>;
|
|
119
|
+
isAborted: (x: z.ParseReturnType<any>) => x is z.INVALID;
|
|
120
|
+
isDirty: <T>(x: z.ParseReturnType<T>) => x is z.OK<T> | z.DIRTY<T>;
|
|
121
|
+
isValid: <T>(x: z.ParseReturnType<T>) => x is z.OK<T>;
|
|
122
|
+
isAsync: <T>(x: z.ParseReturnType<T>) => x is z.AsyncParseReturnType<T>;
|
|
123
|
+
util: typeof z.util;
|
|
124
|
+
objectUtil: typeof z.objectUtil;
|
|
125
|
+
ZodParsedType: {
|
|
126
|
+
string: "string";
|
|
127
|
+
nan: "nan";
|
|
128
|
+
number: "number";
|
|
129
|
+
integer: "integer";
|
|
130
|
+
float: "float";
|
|
131
|
+
boolean: "boolean";
|
|
132
|
+
date: "date";
|
|
133
|
+
bigint: "bigint";
|
|
134
|
+
symbol: "symbol";
|
|
135
|
+
function: "function";
|
|
136
|
+
undefined: "undefined";
|
|
137
|
+
null: "null";
|
|
138
|
+
array: "array";
|
|
139
|
+
object: "object";
|
|
140
|
+
unknown: "unknown";
|
|
141
|
+
promise: "promise";
|
|
142
|
+
void: "void";
|
|
143
|
+
never: "never";
|
|
144
|
+
map: "map";
|
|
145
|
+
set: "set";
|
|
146
|
+
};
|
|
147
|
+
getParsedType: (data: any) => z.ZodParsedType;
|
|
148
|
+
datetimeRegex(args: {
|
|
149
|
+
precision?: number | null;
|
|
150
|
+
offset?: boolean;
|
|
151
|
+
local?: boolean;
|
|
152
|
+
}): RegExp;
|
|
153
|
+
custom<T>(check?: (data: any) => any, _params?: string | (Partial<z.util.Omit<z.ZodCustomIssue, "code">> & {
|
|
154
|
+
fatal?: boolean;
|
|
155
|
+
}) | ((input: any) => Partial<z.util.Omit<z.ZodCustomIssue, "code">> & {
|
|
156
|
+
fatal?: boolean;
|
|
157
|
+
}), fatal?: boolean): z.ZodType<T, z.ZodTypeDef, T>;
|
|
158
|
+
ZodType: typeof z.ZodType;
|
|
159
|
+
ZodString: typeof z.ZodString;
|
|
160
|
+
ZodNumber: typeof z.ZodNumber;
|
|
161
|
+
ZodBigInt: typeof z.ZodBigInt;
|
|
162
|
+
ZodBoolean: typeof z.ZodBoolean;
|
|
163
|
+
ZodDate: typeof z.ZodDate;
|
|
164
|
+
ZodSymbol: typeof z.ZodSymbol;
|
|
165
|
+
ZodUndefined: typeof z.ZodUndefined;
|
|
166
|
+
ZodNull: typeof z.ZodNull;
|
|
167
|
+
ZodAny: typeof z.ZodAny;
|
|
168
|
+
ZodUnknown: typeof z.ZodUnknown;
|
|
169
|
+
ZodNever: typeof z.ZodNever;
|
|
170
|
+
ZodVoid: typeof z.ZodVoid;
|
|
171
|
+
ZodArray: typeof z.ZodArray;
|
|
172
|
+
ZodObject: typeof z.ZodObject;
|
|
173
|
+
ZodUnion: typeof z.ZodUnion;
|
|
174
|
+
ZodDiscriminatedUnion: typeof z.ZodDiscriminatedUnion;
|
|
175
|
+
ZodIntersection: typeof z.ZodIntersection;
|
|
176
|
+
ZodTuple: typeof z.ZodTuple;
|
|
177
|
+
ZodRecord: typeof z.ZodRecord;
|
|
178
|
+
ZodMap: typeof z.ZodMap;
|
|
179
|
+
ZodSet: typeof z.ZodSet;
|
|
180
|
+
ZodFunction: typeof z.ZodFunction;
|
|
181
|
+
ZodLazy: typeof z.ZodLazy;
|
|
182
|
+
ZodLiteral: typeof z.ZodLiteral;
|
|
183
|
+
ZodEnum: typeof z.ZodEnum;
|
|
184
|
+
ZodNativeEnum: typeof z.ZodNativeEnum;
|
|
185
|
+
ZodPromise: typeof z.ZodPromise;
|
|
186
|
+
ZodEffects: typeof z.ZodEffects;
|
|
187
|
+
ZodTransformer: typeof z.ZodEffects;
|
|
188
|
+
ZodOptional: typeof z.ZodOptional;
|
|
189
|
+
ZodNullable: typeof z.ZodNullable;
|
|
190
|
+
ZodDefault: typeof z.ZodDefault;
|
|
191
|
+
ZodCatch: typeof z.ZodCatch;
|
|
192
|
+
ZodNaN: typeof z.ZodNaN;
|
|
193
|
+
BRAND: typeof z.BRAND;
|
|
194
|
+
ZodBranded: typeof z.ZodBranded;
|
|
195
|
+
ZodPipeline: typeof z.ZodPipeline;
|
|
196
|
+
ZodReadonly: typeof z.ZodReadonly;
|
|
197
|
+
Schema: typeof z.ZodType;
|
|
198
|
+
ZodSchema: typeof z.ZodType;
|
|
199
|
+
late: {
|
|
200
|
+
object: <Shape extends z.ZodRawShape>(shape: () => Shape, params?: z.RawCreateParams) => z.ZodObject<Shape, "strip">;
|
|
201
|
+
};
|
|
202
|
+
ZodFirstPartyTypeKind: typeof z.ZodFirstPartyTypeKind;
|
|
203
|
+
coerce: {
|
|
204
|
+
string: (typeof z.ZodString)["create"];
|
|
205
|
+
number: (typeof z.ZodNumber)["create"];
|
|
206
|
+
boolean: (typeof z.ZodBoolean)["create"];
|
|
207
|
+
bigint: (typeof z.ZodBigInt)["create"];
|
|
208
|
+
date: (typeof z.ZodDate)["create"];
|
|
209
|
+
};
|
|
210
|
+
any: (params?: z.RawCreateParams) => z.ZodAny;
|
|
211
|
+
array: <El extends z.ZodTypeAny>(schema: El, params?: z.RawCreateParams) => z.ZodArray<El>;
|
|
212
|
+
bigint: (params?: z.RawCreateParams & {
|
|
213
|
+
coerce?: boolean;
|
|
214
|
+
}) => z.ZodBigInt;
|
|
215
|
+
boolean: (params?: z.RawCreateParams & {
|
|
216
|
+
coerce?: boolean;
|
|
217
|
+
}) => z.ZodBoolean;
|
|
218
|
+
date: (params?: z.RawCreateParams & {
|
|
219
|
+
coerce?: boolean;
|
|
220
|
+
}) => z.ZodDate;
|
|
221
|
+
discriminatedUnion: typeof z.ZodDiscriminatedUnion.create;
|
|
222
|
+
effect: <I extends z.ZodTypeAny>(schema: I, effect: z.Effect<I["_output"]>, params?: z.RawCreateParams) => z.ZodEffects<I, I["_output"]>;
|
|
223
|
+
enum: {
|
|
224
|
+
<U extends string, T extends Readonly<[U, ...U[]]>>(values: T, params?: z.RawCreateParams): z.ZodEnum<z.Writeable<T>>;
|
|
225
|
+
<U extends string, T extends [U, ...U[]]>(values: T, params?: z.RawCreateParams): z.ZodEnum<T>;
|
|
226
|
+
};
|
|
227
|
+
function: typeof z.ZodFunction.create;
|
|
228
|
+
instanceof: <T extends abstract new (..._: any[]) => {}>(cls: T, params?: Partial<z.util.Omit<z.ZodCustomIssue, "code">> & {
|
|
229
|
+
fatal?: boolean;
|
|
230
|
+
}) => z.ZodType<InstanceType<T>, z.ZodTypeDef, InstanceType<T>>;
|
|
231
|
+
intersection: <TSchema extends z.ZodTypeAny, USchema extends z.ZodTypeAny>(left: TSchema, right: USchema, params?: z.RawCreateParams) => z.ZodIntersection<TSchema, USchema>;
|
|
232
|
+
lazy: <Inner extends z.ZodTypeAny>(getter: () => Inner, params?: z.RawCreateParams) => z.ZodLazy<Inner>;
|
|
233
|
+
literal: <Value extends z.Primitive>(value: Value, params?: z.RawCreateParams) => z.ZodLiteral<Value>;
|
|
234
|
+
map: <KeySchema extends z.ZodTypeAny = z.ZodTypeAny, ValueSchema extends z.ZodTypeAny = z.ZodTypeAny>(keyType: KeySchema, valueType: ValueSchema, params?: z.RawCreateParams) => z.ZodMap<KeySchema, ValueSchema>;
|
|
235
|
+
nan: (params?: z.RawCreateParams) => z.ZodNaN;
|
|
236
|
+
nativeEnum: <Elements extends z.EnumLike>(values: Elements, params?: z.RawCreateParams) => z.ZodNativeEnum<Elements>;
|
|
237
|
+
never: (params?: z.RawCreateParams) => z.ZodNever;
|
|
238
|
+
null: (params?: z.RawCreateParams) => z.ZodNull;
|
|
239
|
+
nullable: <Inner extends z.ZodTypeAny>(type: Inner, params?: z.RawCreateParams) => z.ZodNullable<Inner>;
|
|
240
|
+
number: (params?: z.RawCreateParams & {
|
|
241
|
+
coerce?: boolean;
|
|
242
|
+
}) => z.ZodNumber;
|
|
243
|
+
object: <Shape extends z.ZodRawShape>(shape: Shape, params?: z.RawCreateParams) => z.ZodObject<Shape, "strip", z.ZodTypeAny, z.objectOutputType<Shape, z.ZodTypeAny, "strip">, z.objectInputType<Shape, z.ZodTypeAny, "strip">>;
|
|
244
|
+
oboolean: () => z.ZodOptional<z.ZodBoolean>;
|
|
245
|
+
onumber: () => z.ZodOptional<z.ZodNumber>;
|
|
246
|
+
optional: <Inner extends z.ZodTypeAny>(type: Inner, params?: z.RawCreateParams) => z.ZodOptional<Inner>;
|
|
247
|
+
ostring: () => z.ZodOptional<z.ZodString>;
|
|
248
|
+
pipeline: typeof z.ZodPipeline.create;
|
|
249
|
+
preprocess: <I extends z.ZodTypeAny>(preprocess: (arg: unknown, ctx: z.RefinementCtx) => unknown, schema: I, params?: z.RawCreateParams) => z.ZodEffects<I, I["_output"], unknown>;
|
|
250
|
+
promise: <Inner extends z.ZodTypeAny>(schema: Inner, params?: z.RawCreateParams) => z.ZodPromise<Inner>;
|
|
251
|
+
record: typeof z.ZodRecord.create;
|
|
252
|
+
set: <ValueSchema extends z.ZodTypeAny = z.ZodTypeAny>(valueType: ValueSchema, params?: z.RawCreateParams) => z.ZodSet<ValueSchema>;
|
|
253
|
+
strictObject: <Shape extends z.ZodRawShape>(shape: Shape, params?: z.RawCreateParams) => z.ZodObject<Shape, "strict">;
|
|
254
|
+
string: (params?: z.RawCreateParams & {
|
|
255
|
+
coerce?: true;
|
|
256
|
+
}) => z.ZodString;
|
|
257
|
+
symbol: (params?: z.RawCreateParams) => z.ZodSymbol;
|
|
258
|
+
transformer: <I extends z.ZodTypeAny>(schema: I, effect: z.Effect<I["_output"]>, params?: z.RawCreateParams) => z.ZodEffects<I, I["_output"]>;
|
|
259
|
+
tuple: <Items extends [z.ZodTypeAny, ...z.ZodTypeAny[]] | []>(schemas: Items, params?: z.RawCreateParams) => z.ZodTuple<Items, null>;
|
|
260
|
+
undefined: (params?: z.RawCreateParams) => z.ZodUndefined;
|
|
261
|
+
union: <Options extends Readonly<[z.ZodTypeAny, z.ZodTypeAny, ...z.ZodTypeAny[]]>>(types: Options, params?: z.RawCreateParams) => z.ZodUnion<Options>;
|
|
262
|
+
unknown: (params?: z.RawCreateParams) => z.ZodUnknown;
|
|
263
|
+
void: (params?: z.RawCreateParams) => z.ZodVoid;
|
|
264
|
+
NEVER: never;
|
|
265
|
+
ZodIssueCode: {
|
|
266
|
+
invalid_type: "invalid_type";
|
|
267
|
+
invalid_literal: "invalid_literal";
|
|
268
|
+
custom: "custom";
|
|
269
|
+
invalid_union: "invalid_union";
|
|
270
|
+
invalid_union_discriminator: "invalid_union_discriminator";
|
|
271
|
+
invalid_enum_value: "invalid_enum_value";
|
|
272
|
+
unrecognized_keys: "unrecognized_keys";
|
|
273
|
+
invalid_arguments: "invalid_arguments";
|
|
274
|
+
invalid_return_type: "invalid_return_type";
|
|
275
|
+
invalid_date: "invalid_date";
|
|
276
|
+
invalid_string: "invalid_string";
|
|
277
|
+
too_small: "too_small";
|
|
278
|
+
too_big: "too_big";
|
|
279
|
+
invalid_intersection_types: "invalid_intersection_types";
|
|
280
|
+
not_multiple_of: "not_multiple_of";
|
|
281
|
+
not_finite: "not_finite";
|
|
282
|
+
};
|
|
283
|
+
quotelessJson: (obj: any) => string;
|
|
284
|
+
ZodError: typeof z.ZodError;
|
|
285
|
+
};
|
|
286
|
+
/**
|
|
287
|
+
* Type helper to infer the schema type
|
|
288
|
+
*/
|
|
289
|
+
type InferSchema<T extends z.ZodType> = z.infer<T>;
|
|
290
|
+
|
|
291
|
+
interface CompressResult {
|
|
292
|
+
zipBuffer: Uint8Array;
|
|
293
|
+
checksum: string;
|
|
294
|
+
}
|
|
295
|
+
interface DecompressResult {
|
|
296
|
+
source: string;
|
|
297
|
+
bundle: string;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Compress source and bundle into a ZIP archive
|
|
301
|
+
* Uses fflate for fast, modern compression
|
|
302
|
+
*/
|
|
303
|
+
declare function compressTask(source: string, bundle: string): CompressResult;
|
|
304
|
+
/**
|
|
305
|
+
* Decompress ZIP archive and extract source and bundle files
|
|
306
|
+
* Uses fflate for fast decompression
|
|
307
|
+
*/
|
|
308
|
+
declare function decompressTask(zipBuffer: Uint8Array | ArrayBuffer): DecompressResult;
|
|
309
|
+
|
|
310
|
+
export { type Call, type CompressResult, type DecompressResult, type FailResult, type InferSchema, type SuccessResult, type TaskDefinition, type TaskResult, type ThymeContext, compressTask, decompressTask, defineTask, zodExtended as z };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
// src/task.ts
|
|
2
|
+
function defineTask(definition) {
|
|
3
|
+
return definition;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// src/schema.ts
|
|
7
|
+
import { getAddress, isAddress } from "viem";
|
|
8
|
+
import { z } from "zod";
|
|
9
|
+
var zodExtended = {
|
|
10
|
+
...z,
|
|
11
|
+
/**
|
|
12
|
+
* Validates an Ethereum address and returns viem's Address type
|
|
13
|
+
* Accepts both checksummed and non-checksummed addresses
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```typescript
|
|
17
|
+
* import { zodExtended as z } from '@thyme-sh/sdk'
|
|
18
|
+
*
|
|
19
|
+
* const schema = z.object({
|
|
20
|
+
* targetAddress: z.address(),
|
|
21
|
+
* })
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
address: () => z.string().refine((val) => isAddress(val), {
|
|
25
|
+
message: "Invalid Ethereum address"
|
|
26
|
+
}).transform((val) => getAddress(val))
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// src/archive.ts
|
|
30
|
+
import { strFromU8, strToU8, unzipSync, zipSync } from "fflate";
|
|
31
|
+
function compressTask(source, bundle) {
|
|
32
|
+
const files = {
|
|
33
|
+
"source.ts": strToU8(source),
|
|
34
|
+
"bundle.js": strToU8(bundle)
|
|
35
|
+
};
|
|
36
|
+
const compressed = zipSync(files, {
|
|
37
|
+
level: 6
|
|
38
|
+
// Balanced compression
|
|
39
|
+
});
|
|
40
|
+
let hash = 0;
|
|
41
|
+
for (let i = 0; i < compressed.length; i++) {
|
|
42
|
+
const byte = compressed[i];
|
|
43
|
+
if (byte !== void 0) {
|
|
44
|
+
hash = (hash << 5) - hash + byte;
|
|
45
|
+
hash = hash & hash;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
const checksum = Math.abs(hash).toString(16);
|
|
49
|
+
return {
|
|
50
|
+
zipBuffer: compressed,
|
|
51
|
+
checksum
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function decompressTask(zipBuffer) {
|
|
55
|
+
const uint8Array = zipBuffer instanceof ArrayBuffer ? new Uint8Array(zipBuffer) : zipBuffer;
|
|
56
|
+
const decompressed = unzipSync(uint8Array);
|
|
57
|
+
const sourceBytes = decompressed["source.ts"];
|
|
58
|
+
const bundleBytes = decompressed["bundle.js"];
|
|
59
|
+
if (!sourceBytes) {
|
|
60
|
+
throw new Error("source.ts not found in ZIP archive");
|
|
61
|
+
}
|
|
62
|
+
if (!bundleBytes) {
|
|
63
|
+
throw new Error("bundle.js not found in ZIP archive");
|
|
64
|
+
}
|
|
65
|
+
const source = strFromU8(sourceBytes);
|
|
66
|
+
const bundle = strFromU8(bundleBytes);
|
|
67
|
+
return {
|
|
68
|
+
source,
|
|
69
|
+
bundle
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export {
|
|
73
|
+
compressTask,
|
|
74
|
+
decompressTask,
|
|
75
|
+
defineTask,
|
|
76
|
+
zodExtended as z
|
|
77
|
+
};
|
|
78
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/task.ts","../src/schema.ts","../src/archive.ts"],"sourcesContent":["import type { z } from 'zod'\nimport type { TaskDefinition } from './types'\n\n/**\n * Define a Web3 automation task\n *\n * @example\n * ```typescript\n * import { defineTask, z } from '@thyme-sh/sdk'\n * import { encodeFunctionData } from 'viem'\n *\n * const abi = [\n * 'function transfer(address to, uint256 amount) returns (bool)',\n * ] as const\n *\n * export default defineTask({\n * schema: z.object({\n * targetAddress: z.address(),\n * }),\n * async run(ctx) {\n * return {\n * canExec: true,\n * calls: [{\n * to: ctx.args.targetAddress,\n * data: encodeFunctionData({\n * abi,\n * functionName: 'transfer',\n * args: [recipientAddress, 1000n],\n * }),\n * }]\n * }\n * }\n * })\n * ```\n */\nexport function defineTask<TSchema extends z.ZodType>(\n\tdefinition: TaskDefinition<TSchema>,\n): TaskDefinition<TSchema> {\n\treturn definition\n}\n","import { type Address, getAddress, isAddress } from 'viem'\nimport { z } from 'zod'\n\n/**\n * Extended Zod with Ethereum address validation\n */\nexport const zodExtended = {\n\t...z,\n\t/**\n\t * Validates an Ethereum address and returns viem's Address type\n\t * Accepts both checksummed and non-checksummed addresses\n\t *\n\t * @example\n\t * ```typescript\n\t * import { zodExtended as z } from '@thyme-sh/sdk'\n\t *\n\t * const schema = z.object({\n\t * targetAddress: z.address(),\n\t * })\n\t * ```\n\t */\n\taddress: () =>\n\t\tz\n\t\t\t.string()\n\t\t\t.refine((val): val is Address => isAddress(val), {\n\t\t\t\tmessage: 'Invalid Ethereum address',\n\t\t\t})\n\t\t\t.transform((val) => getAddress(val)),\n}\n\n/**\n * Type helper to infer the schema type\n */\nexport type InferSchema<T extends z.ZodType> = z.infer<T>\n","import { strFromU8, strToU8, unzipSync, zipSync } from 'fflate'\n\nexport interface CompressResult {\n\tzipBuffer: Uint8Array\n\tchecksum: string\n}\n\nexport interface DecompressResult {\n\tsource: string\n\tbundle: string\n}\n\n/**\n * Compress source and bundle into a ZIP archive\n * Uses fflate for fast, modern compression\n */\nexport function compressTask(source: string, bundle: string): CompressResult {\n\t// Create ZIP archive with both files\n\tconst files = {\n\t\t'source.ts': strToU8(source),\n\t\t'bundle.js': strToU8(bundle),\n\t}\n\n\tconst compressed = zipSync(files, {\n\t\tlevel: 6, // Balanced compression\n\t})\n\n\t// Calculate checksum (simple hash for now)\n\tlet hash = 0\n\tfor (let i = 0; i < compressed.length; i++) {\n\t\tconst byte = compressed[i]\n\t\tif (byte !== undefined) {\n\t\t\thash = (hash << 5) - hash + byte\n\t\t\thash = hash & hash // Convert to 32bit integer\n\t\t}\n\t}\n\tconst checksum = Math.abs(hash).toString(16)\n\n\treturn {\n\t\tzipBuffer: compressed,\n\t\tchecksum,\n\t}\n}\n\n/**\n * Decompress ZIP archive and extract source and bundle files\n * Uses fflate for fast decompression\n */\nexport function decompressTask(\n\tzipBuffer: Uint8Array | ArrayBuffer,\n): DecompressResult {\n\t// Convert ArrayBuffer to Uint8Array if needed\n\tconst uint8Array =\n\t\tzipBuffer instanceof ArrayBuffer ? new Uint8Array(zipBuffer) : zipBuffer\n\n\t// Decompress ZIP\n\tconst decompressed = unzipSync(uint8Array)\n\n\t// Extract files\n\tconst sourceBytes = decompressed['source.ts']\n\tconst bundleBytes = decompressed['bundle.js']\n\n\tif (!sourceBytes) {\n\t\tthrow new Error('source.ts not found in ZIP archive')\n\t}\n\n\tif (!bundleBytes) {\n\t\tthrow new Error('bundle.js not found in ZIP archive')\n\t}\n\n\t// Convert bytes to strings\n\tconst source = strFromU8(sourceBytes)\n\tconst bundle = strFromU8(bundleBytes)\n\n\treturn {\n\t\tsource,\n\t\tbundle,\n\t}\n}\n"],"mappings":";AAmCO,SAAS,WACf,YAC0B;AAC1B,SAAO;AACR;;;ACvCA,SAAuB,YAAY,iBAAiB;AACpD,SAAS,SAAS;AAKX,IAAM,cAAc;AAAA,EAC1B,GAAG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcH,SAAS,MACR,EACE,OAAO,EACP,OAAO,CAAC,QAAwB,UAAU,GAAG,GAAG;AAAA,IAChD,SAAS;AAAA,EACV,CAAC,EACA,UAAU,CAAC,QAAQ,WAAW,GAAG,CAAC;AACtC;;;AC5BA,SAAS,WAAW,SAAS,WAAW,eAAe;AAgBhD,SAAS,aAAa,QAAgB,QAAgC;AAE5E,QAAM,QAAQ;AAAA,IACb,aAAa,QAAQ,MAAM;AAAA,IAC3B,aAAa,QAAQ,MAAM;AAAA,EAC5B;AAEA,QAAM,aAAa,QAAQ,OAAO;AAAA,IACjC,OAAO;AAAA;AAAA,EACR,CAAC;AAGD,MAAI,OAAO;AACX,WAAS,IAAI,GAAG,IAAI,WAAW,QAAQ,KAAK;AAC3C,UAAM,OAAO,WAAW,CAAC;AACzB,QAAI,SAAS,QAAW;AACvB,cAAQ,QAAQ,KAAK,OAAO;AAC5B,aAAO,OAAO;AAAA,IACf;AAAA,EACD;AACA,QAAM,WAAW,KAAK,IAAI,IAAI,EAAE,SAAS,EAAE;AAE3C,SAAO;AAAA,IACN,WAAW;AAAA,IACX;AAAA,EACD;AACD;AAMO,SAAS,eACf,WACmB;AAEnB,QAAM,aACL,qBAAqB,cAAc,IAAI,WAAW,SAAS,IAAI;AAGhE,QAAM,eAAe,UAAU,UAAU;AAGzC,QAAM,cAAc,aAAa,WAAW;AAC5C,QAAM,cAAc,aAAa,WAAW;AAE5C,MAAI,CAAC,aAAa;AACjB,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACrD;AAEA,MAAI,CAAC,aAAa;AACjB,UAAM,IAAI,MAAM,oCAAoC;AAAA,EACrD;AAGA,QAAM,SAAS,UAAU,WAAW;AACpC,QAAM,SAAS,UAAU,WAAW;AAEpC,SAAO;AAAA,IACN;AAAA,IACA;AAAA,EACD;AACD;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@thyme-sh/sdk",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "SDK for authoring Web3 automation tasks",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsup",
|
|
19
|
+
"dev": "tsup --watch",
|
|
20
|
+
"test": "echo \"No tests yet\""
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"web3",
|
|
24
|
+
"automation",
|
|
25
|
+
"ethereum",
|
|
26
|
+
"tasks",
|
|
27
|
+
"thyme"
|
|
28
|
+
],
|
|
29
|
+
"author": "",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"fflate": "^0.8.2",
|
|
33
|
+
"viem": "^2.21.54",
|
|
34
|
+
"zod": "^3.24.1"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"tsup": "^8.3.5",
|
|
38
|
+
"typescript": "^5.7.2"
|
|
39
|
+
}
|
|
40
|
+
}
|