@baliola/smart-account-sdk 0.3.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/LICENSE +37 -0
- package/README.md +374 -0
- package/dist/abi-ziHt832n.js +1470 -0
- package/dist/accounts/index.d.ts +20 -0
- package/dist/accounts/index.js +2 -0
- package/dist/accounts-Bw0IrOJ1.js +229 -0
- package/dist/actions/index.d.ts +37 -0
- package/dist/actions/index.js +2 -0
- package/dist/auth/index.d.ts +35 -0
- package/dist/auth/index.js +2 -0
- package/dist/base-v7RyiDFz.js +104 -0
- package/dist/chains/index.d.ts +2 -0
- package/dist/chains/index.js +33 -0
- package/dist/classifyBundlerError-BqFLORNt.js +161 -0
- package/dist/clients/index.d.ts +86 -0
- package/dist/clients/index.js +3 -0
- package/dist/clients-B17dl_fh.js +134 -0
- package/dist/deployments-D4U_osAQ.js +10 -0
- package/dist/errors/index.d.ts +136 -0
- package/dist/errors/index.js +3 -0
- package/dist/index-BVqNo3O0.d.ts +222 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +12 -0
- package/dist/receipt-Ceeclfnv.d.ts +24 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +1 -0
- package/dist/types-BcsdeCby.d.ts +25 -0
- package/dist/types-CD0TvpY4.d.ts +60 -0
- package/dist/validateApiKey-lUfEM5W0.js +68 -0
- package/dist/writeContract-AyQox2dQ.js +371 -0
- package/dist/writeContract-CdcmYmx0.d.ts +184 -0
- package/package.json +85 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
Copyright (c) 2026 Baliola. All rights reserved.
|
|
2
|
+
|
|
3
|
+
PROPRIETARY AND CONFIDENTIAL
|
|
4
|
+
|
|
5
|
+
This software, including its source code, compiled output, type definitions,
|
|
6
|
+
documentation, and any associated materials (collectively, the "Software"), is
|
|
7
|
+
the proprietary property of Baliola. All rights, title, and interest in and to
|
|
8
|
+
the Software are and shall remain the exclusive property of Baliola.
|
|
9
|
+
|
|
10
|
+
Access to the Software is granted only to parties expressly authorized by
|
|
11
|
+
Baliola, and solely under the terms of a separate written agreement with
|
|
12
|
+
Baliola. No rights or licenses are granted by implication, estoppel, or
|
|
13
|
+
otherwise.
|
|
14
|
+
|
|
15
|
+
Without Baliola's prior written consent, the following are prohibited:
|
|
16
|
+
|
|
17
|
+
1. Redistribution of the Software, in whole or in part, in source or
|
|
18
|
+
compiled form, to any third party.
|
|
19
|
+
2. Modification, adaptation, translation, or creation of derivative works
|
|
20
|
+
based on the Software.
|
|
21
|
+
3. Reverse engineering, decompilation, or disassembly of the Software,
|
|
22
|
+
except to the extent such restriction is expressly prohibited by
|
|
23
|
+
applicable law.
|
|
24
|
+
4. Sublicensing, leasing, renting, selling, or otherwise transferring any
|
|
25
|
+
rights in the Software.
|
|
26
|
+
5. Removing, altering, or obscuring any copyright, trademark, or other
|
|
27
|
+
proprietary notices appearing in the Software.
|
|
28
|
+
|
|
29
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
30
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
31
|
+
FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NONINFRINGEMENT. IN NO EVENT
|
|
32
|
+
SHALL BALIOLA, ITS AFFILIATES, OR CONTRIBUTORS BE LIABLE FOR ANY CLAIM,
|
|
33
|
+
DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT, OR
|
|
34
|
+
OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
35
|
+
USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
36
|
+
|
|
37
|
+
For licensing inquiries, contact: <info@baliola.io>
|
package/README.md
ADDED
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
# @baliola/smart-account-sdk
|
|
2
|
+
|
|
3
|
+
Client-side TypeScript SDK for Baliola's ERC-4337 v0.7 stack on **MAC chain**. A thin viem extension that handles UserOperation packing, signing, bundler RPC, and Gas Allowance Pool (paymaster) wiring. Pick a chain by name, plug in your API key, send transactions.
|
|
4
|
+
|
|
5
|
+
```ts
|
|
6
|
+
const account = await toSmartAccount({ owner, chain: "macTestnet" });
|
|
7
|
+
const client = await createSmartAccountClient({
|
|
8
|
+
account,
|
|
9
|
+
chain: "macTestnet",
|
|
10
|
+
apiKey: BALIOLA_KEY,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
const userOpHash = await client.writeContract({
|
|
14
|
+
address: nft,
|
|
15
|
+
abi: nftAbi,
|
|
16
|
+
functionName: "mint",
|
|
17
|
+
args: [1n],
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const receipt = await client.waitForUserOperationReceipt({ userOpHash });
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Install
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
bun add @baliola/smart-account-sdk viem
|
|
27
|
+
# or: npm install / pnpm add
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`viem` (`^2.46`) is a peer dependency. Install it alongside.
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
36
|
+
import {
|
|
37
|
+
createSmartAccountClient,
|
|
38
|
+
toSmartAccount,
|
|
39
|
+
} from "@baliola/smart-account-sdk";
|
|
40
|
+
|
|
41
|
+
const owner = privateKeyToAccount(process.env.OWNER_KEY as `0x${string}`);
|
|
42
|
+
|
|
43
|
+
const account = await toSmartAccount({
|
|
44
|
+
owner,
|
|
45
|
+
chain: "macTestnet",
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// createSmartAccountClient is async. It validates the API key against
|
|
49
|
+
// baliola-auth before returning.
|
|
50
|
+
const client = await createSmartAccountClient({
|
|
51
|
+
account,
|
|
52
|
+
chain: "macTestnet",
|
|
53
|
+
apiKey: process.env.BALIOLA_KEY!,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const userOpHash = await client.writeContract({
|
|
57
|
+
address: "0xYourContract",
|
|
58
|
+
abi: yourAbi,
|
|
59
|
+
functionName: "doSomething",
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
const receipt = await client.waitForUserOperationReceipt({ userOpHash });
|
|
63
|
+
console.log("included in tx:", receipt.txHash);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Chains
|
|
67
|
+
|
|
68
|
+
The SDK is opinionated about MAC. Pick a chain by name and everything else is preconfigured: chain RPC, bundler RPC, and the auth service URL.
|
|
69
|
+
|
|
70
|
+
| `chain` | Network |
|
|
71
|
+
|---|---|
|
|
72
|
+
| `"macTestnet"` | MAC Testnet |
|
|
73
|
+
| `"macMainnet"` | MAC Mainnet |
|
|
74
|
+
|
|
75
|
+
```ts
|
|
76
|
+
import { macTestnet, macMainnet, resolveChain, MAC_CHAINS } from "@baliola/smart-account-sdk";
|
|
77
|
+
|
|
78
|
+
resolveChain("macTestnet"); // viem Chain object
|
|
79
|
+
Object.keys(MAC_CHAINS); // ["macTestnet", "macMainnet"]
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## API Key Validation
|
|
83
|
+
|
|
84
|
+
`createSmartAccountClient` validates the API key once at construction time. On success, the key info (including quota) is exposed on `client.apiKey`. On rejection it throws `ApiKeyInvalidError`; on transport failure it throws `BaliolaAuthUnreachableError`.
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
try {
|
|
88
|
+
const client = await createSmartAccountClient({
|
|
89
|
+
account,
|
|
90
|
+
chain: "macTestnet",
|
|
91
|
+
apiKey: BALIOLA_KEY,
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
client.apiKey.id; // apiKeyId (uuid)
|
|
95
|
+
client.apiKey.accountId; // baliola account uuid
|
|
96
|
+
client.apiKey.module; // "smart-account"
|
|
97
|
+
client.apiKey.quota.callsRemaining; // remaining calls in the period
|
|
98
|
+
client.apiKey.quota.periodResetsAt; // ISO 8601 timestamp
|
|
99
|
+
} catch (err) {
|
|
100
|
+
if (err instanceof ApiKeyInvalidError) {
|
|
101
|
+
switch (err.reason) {
|
|
102
|
+
case "revoked":
|
|
103
|
+
case "expired":
|
|
104
|
+
case "not_found":
|
|
105
|
+
case "wrong_module":
|
|
106
|
+
case "module_inactive":
|
|
107
|
+
case "origin_not_allowed":
|
|
108
|
+
// bad key; user needs to fix it
|
|
109
|
+
break;
|
|
110
|
+
case "quota_exceeded":
|
|
111
|
+
case "rate_limited":
|
|
112
|
+
// back off using err.retryAfterSeconds
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
} else if (err instanceof BaliolaAuthUnreachableError) {
|
|
116
|
+
// baliola-auth down or network issue; safe to retry
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Each construction consumes one quota call.** Cache the client; don't rebuild it on every request.
|
|
122
|
+
|
|
123
|
+
To point at a custom auth host (for staging or dev), pass `authUrl`:
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
await createSmartAccountClient({
|
|
127
|
+
account,
|
|
128
|
+
chain: "macTestnet",
|
|
129
|
+
apiKey: BALIOLA_KEY,
|
|
130
|
+
authUrl: "https://your-auth-host",
|
|
131
|
+
});
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## `createSmartAccountClient` options
|
|
135
|
+
|
|
136
|
+
```ts
|
|
137
|
+
await createSmartAccountClient({
|
|
138
|
+
account, // required, from toSmartAccount
|
|
139
|
+
chain, // required, "macTestnet" | "macMainnet"
|
|
140
|
+
apiKey, // required
|
|
141
|
+
authUrl?, // override the chain's default auth host
|
|
142
|
+
paymasterAddress?, // override the chain's default Gas Allowance Pool
|
|
143
|
+
bundlerUrl?, // override the default bundler URL
|
|
144
|
+
bundlerTransport?, // full viem Transport escape hatch
|
|
145
|
+
transport?, // chain RPC transport (defaults to chain's built-in RPC)
|
|
146
|
+
});
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
Resolution precedence:
|
|
150
|
+
|
|
151
|
+
- **Auth URL**: `authUrl` then the default for the chain.
|
|
152
|
+
- **Chain RPC**: `transport` then `http()` of the chain default.
|
|
153
|
+
- **Bundler RPC**: `bundlerTransport` then `bundlerUrl` then the chain default.
|
|
154
|
+
- **Paymaster**: `paymasterAddress` then the chain's registered Gas Allowance Pool, otherwise throw `PaymasterConfigError`.
|
|
155
|
+
|
|
156
|
+
## `toSmartAccount` options
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
toSmartAccount({
|
|
160
|
+
owner, // required, viem Account or "0x"-prefixed 32-byte private key
|
|
161
|
+
chain, // required, "macTestnet" | "macMainnet"
|
|
162
|
+
salt?, // CREATE2 salt for counterfactual address (default 0n)
|
|
163
|
+
nonceKey?, // EntryPoint nonce key (default 0n)
|
|
164
|
+
transport?, // chain RPC transport (defaults to chain's built-in RPC)
|
|
165
|
+
publicClient?, // share a publicClient across calls (default: built internally)
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Returned `ISmartAccount` is counterfactual until the first UserOperation is sent. The factory call is injected automatically.
|
|
170
|
+
|
|
171
|
+
## `writeContract`, the single write verb
|
|
172
|
+
|
|
173
|
+
Same shape for everything: a typed call, a raw call, or a batch.
|
|
174
|
+
|
|
175
|
+
### Typed contract call
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
const userOpHash = await client.writeContract({
|
|
179
|
+
address: counter,
|
|
180
|
+
abi: counterAbi,
|
|
181
|
+
functionName: "increment",
|
|
182
|
+
args: [],
|
|
183
|
+
value: 0n, // optional
|
|
184
|
+
});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Raw call (ETH transfer or pre-encoded data)
|
|
188
|
+
|
|
189
|
+
```ts
|
|
190
|
+
// Pure native transfer
|
|
191
|
+
await client.writeContract({ to: recipient, value: 1n });
|
|
192
|
+
|
|
193
|
+
// Pre-encoded calldata
|
|
194
|
+
await client.writeContract({ to: target, value: 0n, data: "0xabcd..." });
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Batch with an array
|
|
198
|
+
|
|
199
|
+
Mixed typed and raw entries are allowed in one batch. The whole batch is one UserOperation submitted via `SimpleAccount.executeBatch`.
|
|
200
|
+
|
|
201
|
+
```ts
|
|
202
|
+
const userOpHash = await client.writeContract([
|
|
203
|
+
{ address: usdc, abi: erc20Abi, functionName: "approve", args: [router, amount] },
|
|
204
|
+
{ address: router, abi: routerAbi, functionName: "swap", args: [...] },
|
|
205
|
+
{ to: refundAddr, value: 1n }, // raw entry alongside typed ones
|
|
206
|
+
]);
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Overrides
|
|
210
|
+
|
|
211
|
+
A second optional argument lets you override UserOperation-level fields (gas, fee, paymaster, nonce). Most callers never touch this.
|
|
212
|
+
|
|
213
|
+
```ts
|
|
214
|
+
await client.writeContract(input, {
|
|
215
|
+
preVerificationGas: 200_000n,
|
|
216
|
+
maxFeePerGas: 5_000_000_000n,
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
## Receipts
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
// One-shot; returns null if not yet included
|
|
224
|
+
const maybe = await client.getUserOperationReceipt({ userOpHash });
|
|
225
|
+
|
|
226
|
+
// Poll until included or timeout
|
|
227
|
+
const receipt = await client.waitForUserOperationReceipt({
|
|
228
|
+
userOpHash,
|
|
229
|
+
timeout: 60_000,
|
|
230
|
+
pollingInterval: 1_000,
|
|
231
|
+
signal: abortSignal, // optional AbortSignal
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
receipt.userOpHash; // ERC-4337 hash
|
|
235
|
+
receipt.txHash; // on-chain handleOps tx hash
|
|
236
|
+
receipt.blockNumber;
|
|
237
|
+
receipt.success;
|
|
238
|
+
receipt.actualGasUsed;
|
|
239
|
+
receipt.actualGasCost;
|
|
240
|
+
receipt.logs; // pre-sliced to this UserOp
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Watching events
|
|
244
|
+
|
|
245
|
+
Subscribe to `EntryPoint.UserOperationEvent` filtered by sender or a specific `userOpHash`. The SDK decodes each match into typed fields.
|
|
246
|
+
|
|
247
|
+
```ts
|
|
248
|
+
const unwatch = client.watchUserOperations({
|
|
249
|
+
// Defaults to your account's address when omitted
|
|
250
|
+
sender: account.address,
|
|
251
|
+
onUserOp(event) {
|
|
252
|
+
console.log(event.userOpHash, event.success, event.actualGasCost);
|
|
253
|
+
},
|
|
254
|
+
onError(err) { console.error(err); },
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
unwatch(); // stop the subscription
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
## Paymaster (Gas Allowance Pool)
|
|
261
|
+
|
|
262
|
+
Every UserOperation is sponsored by a paymaster. The default is the **Gas Allowance Pool (GAP)** registered for the chain, no configuration required.
|
|
263
|
+
|
|
264
|
+
```ts
|
|
265
|
+
// Default: uses the chain's GAP
|
|
266
|
+
await createSmartAccountClient({ account, chain: "macTestnet", apiKey });
|
|
267
|
+
|
|
268
|
+
// Override: route through a different paymaster contract
|
|
269
|
+
await createSmartAccountClient({
|
|
270
|
+
account, chain: "macTestnet", apiKey,
|
|
271
|
+
paymasterAddress: "0x...",
|
|
272
|
+
});
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
`paymasterAddress` is validated at construction. Invalid or zero addresses throw `PaymasterConfigError`. Self-funded mode is not supported.
|
|
276
|
+
|
|
277
|
+
## Errors
|
|
278
|
+
|
|
279
|
+
Every SDK error extends `SmartAccountSDKError`. The library is **opinionated about messages**: `err.message` is always written for an end user (short, polite, and safe to surface directly in product UI). Technical detail lives on:
|
|
280
|
+
|
|
281
|
+
- `err.code`: internal tag or AA code (e.g. `"API_KEY_INVALID"`, `"AA24"`)
|
|
282
|
+
- `err.reason`: typed enum on errors that have one (`ApiKeyInvalidError`, `PaymasterConfigError`)
|
|
283
|
+
- `err.detail`: optional technical sentence for developer logs
|
|
284
|
+
- `err.cause`: the underlying transport or library error
|
|
285
|
+
|
|
286
|
+
Discriminate with `instanceof`, not message matching.
|
|
287
|
+
|
|
288
|
+
```text
|
|
289
|
+
SmartAccountSDKError // root
|
|
290
|
+
├─ UserOperationReceiptTimeoutError
|
|
291
|
+
├─ PaymasterConfigError // dev-config error, carries `reason`
|
|
292
|
+
├─ ApiKeyInvalidError // baliola-auth rejected the key (carries `reason`)
|
|
293
|
+
├─ BaliolaAuthUnreachableError // network or 5xx talking to baliola-auth
|
|
294
|
+
├─ BundlerRpcError
|
|
295
|
+
│ ├─ InvalidUserOperationError // bundler rejected the params
|
|
296
|
+
│ ├─ UserOperationRejectedError // bundler dropped on submit
|
|
297
|
+
│ └─ BundlerUnreachableError // network or timeout
|
|
298
|
+
└─ UserOperationRevertError // AA-code reverts
|
|
299
|
+
├─ AccountFactoryError // AA1x
|
|
300
|
+
├─ AccountValidationError // AA2x: signature, nonce, prefund
|
|
301
|
+
├─ PaymasterValidationError // AA3x: paymaster rejection
|
|
302
|
+
└─ BundleFrameError // AA9x
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Surfacing errors
|
|
306
|
+
|
|
307
|
+
You can pipe `err.message` straight into a toast or banner. It's already user-safe:
|
|
308
|
+
|
|
309
|
+
```ts
|
|
310
|
+
try {
|
|
311
|
+
await client.writeContract({ /* ... */ });
|
|
312
|
+
} catch (err) {
|
|
313
|
+
toast(err instanceof Error ? err.message : "Something went wrong.");
|
|
314
|
+
console.error(err); // full technical detail still on err.detail / err.cause
|
|
315
|
+
}
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
### Default user messages
|
|
319
|
+
|
|
320
|
+
| Error | `err.message` |
|
|
321
|
+
|---|---|
|
|
322
|
+
| `ApiKeyInvalidError` (reason=`revoked`) | "This API key has been revoked. Please generate a new one." |
|
|
323
|
+
| `ApiKeyInvalidError` (reason=`expired`) | "This API key has expired. Please generate a new one." |
|
|
324
|
+
| `ApiKeyInvalidError` (reason=`quota_exceeded`) | "You've hit the request limit. Please try again later." |
|
|
325
|
+
| `ApiKeyInvalidError` (reason=`rate_limited`) | "Too many requests. Please slow down and try again." |
|
|
326
|
+
| `ApiKeyInvalidError` (reason=`not_found`) | "Invalid API key. Please check your credentials." |
|
|
327
|
+
| `BaliolaAuthUnreachableError` | "Authentication service is temporarily unavailable. Please try again in a moment." |
|
|
328
|
+
| `BundlerUnreachableError` | "Couldn't reach the network. Please check your connection and try again." |
|
|
329
|
+
| `UserOperationReceiptTimeoutError` | "Your transaction is taking longer than expected. Please check the block explorer or try again." |
|
|
330
|
+
| `PaymasterValidationError` (AA3x) | "Gas sponsorship was declined for this transaction. Please try again later." |
|
|
331
|
+
| `AccountValidationError` (AA2x) | "Your transaction couldn't be authorized. Please try again." |
|
|
332
|
+
| `AccountFactoryError` (AA1x) | "We couldn't set up your smart account. Please try again." |
|
|
333
|
+
| `BundleFrameError` (AA9x) | "Something went wrong submitting your transaction. Please try again." |
|
|
334
|
+
| `InvalidUserOperationError` | "Your transaction was rejected before submission. Please try again." |
|
|
335
|
+
| `UserOperationRejectedError` | "Your transaction was rejected by the network. Please try again." |
|
|
336
|
+
| `PaymasterConfigError` | "Gas sponsorship isn't available for this network. Please contact support." |
|
|
337
|
+
|
|
338
|
+
### Tailoring the copy
|
|
339
|
+
|
|
340
|
+
If you need different tone, branding, or i18n, switch on the typed fields and write your own copy. Every error carries enough metadata to do so:
|
|
341
|
+
|
|
342
|
+
```ts
|
|
343
|
+
function copy(err: unknown): string {
|
|
344
|
+
if (err instanceof ApiKeyInvalidError) {
|
|
345
|
+
switch (err.reason) {
|
|
346
|
+
case "quota_exceeded":
|
|
347
|
+
return err.retryAfterSeconds
|
|
348
|
+
? `Limit hit, try again in ${err.retryAfterSeconds}s.`
|
|
349
|
+
: "Daily limit reached.";
|
|
350
|
+
case "revoked": return "Your access has been revoked.";
|
|
351
|
+
// ...
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
if (err instanceof Error) return err.message; // sensible default
|
|
355
|
+
return "Something went wrong.";
|
|
356
|
+
}
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## Subpath imports
|
|
360
|
+
|
|
361
|
+
```ts
|
|
362
|
+
import { createSmartAccountClient } from "@baliola/smart-account-sdk";
|
|
363
|
+
import { toSmartAccount } from "@baliola/smart-account-sdk/accounts";
|
|
364
|
+
import { writeContract } from "@baliola/smart-account-sdk/actions";
|
|
365
|
+
import { validateApiKey, DEFAULT_AUTH_URLS } from "@baliola/smart-account-sdk/auth";
|
|
366
|
+
import { macTestnet, MAC_CHAINS } from "@baliola/smart-account-sdk/chains";
|
|
367
|
+
import { DEFAULT_BUNDLER_URLS } from "@baliola/smart-account-sdk/clients";
|
|
368
|
+
import { SmartAccountSDKError } from "@baliola/smart-account-sdk/errors";
|
|
369
|
+
import type { UserOperationReceipt } from "@baliola/smart-account-sdk/types";
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## License
|
|
373
|
+
|
|
374
|
+
Proprietary. Copyright 2026 Baliola. All rights reserved. See [LICENSE](./LICENSE).
|