@ar.io/sdk 3.20.0 → 3.21.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 CHANGED
@@ -12,9 +12,8 @@ This is the home of [ar.io] SDK. This SDK provides functionality for interacting
12
12
  - [Installation](#installation)
13
13
  - [Quick Start](#quick-start)
14
14
  - [Usage](#usage)
15
- - [Networks (Mainnet, Testnet, etc.)](#networks-mainnet-testnet-etc)
16
- - [ARIO](#ario)
17
- - [Arweave Name Tokens (ANT's)](#arweave-name-tokens-ants)
15
+ - [ARIO Contract](#ario-contract)
16
+ - [ANT Contracts](#ant-contracts)
18
17
  - [Token Conversion](#token-conversion)
19
18
  - [Logging](#logging)
20
19
  - [Pagination](#pagination)
@@ -162,109 +161,7 @@ The SDK provides TypeScript types. When you import the SDK in a TypeScript proje
162
161
  > [!NOTE]
163
162
  > Typescript version 5.3 or higher is recommended.
164
163
 
165
- ## Networks (Mainnet, Testnet, etc.)
166
-
167
- The SDK provides the following process IDs for the mainnet and testnet environments:
168
-
169
- - `ARIO_MAINNET_PROCESS_ID` - Mainnet ARIO process ID (production)
170
- - `ARIO_TESTNET_PROCESS_ID` - Testnet ARIO process ID (testing and development)
171
- - `ARIO_DEVNET_PROCESS_ID` - Devnet ARIO process ID (development)
172
-
173
- As of `v3.8.1` the SDK defaults all API interactions to **mainnet**. To use the **testnet** or **devnet** provide the appropriate `ARIO_TESTNET_PROCESS_ID` or `ARIO_DEVNET_PROCESS_ID` when initializing the client.
174
-
175
- ### Mainnet
176
-
177
- As of `v3.8.1` the SDK defaults all API interactions to **mainnet**. To use the **testnet** or **devnet** provide the appropriate `ARIO_TESTNET_PROCESS_ID` or `ARIO_DEVNET_PROCESS_ID` when initializing the client.
178
-
179
- ```typescript
180
- import { ARIO } from '@ar.io/sdk';
181
-
182
- const ario = ARIO.mainnet(); // or ARIO.init()
183
- ```
184
-
185
- ### Testnet
186
-
187
- ```typescript
188
- import { ARIO } from '@ar.io/sdk';
189
-
190
- const testnet = ARIO.testnet(); // or ARIO.init({ processId: ARIO_TESTNET_PROCESS_ID })
191
- ```
192
-
193
- #### Faucet
194
-
195
- The SDK provides APIs for claiming tokens via a faucet on the AR.IO Testnet process (`tARIO`) via the [ar-io-testnet-faucet] service. All token requests require a captcha to be solved, and the faucet is rate limited to prevent abuse.
196
-
197
- To claim testnet tokens from the testnet token faucet, you can use one of the following methods:
198
-
199
- 1. Visit [faucet.ar.io](https://faucet.ar.io) - the easiest way to quickly get tokens for testing for a single address.
200
-
201
- 2. Programmatically via the SDK - useful if you need to claim tokens for multiple addresses or dynamically within your application.
202
-
203
- - `ARIO.testnet().faucet.captchaUrl()` - returns the captcha URL for the testnet faucet. Open this URL in a new browser window and listen for the `ario-jwt-success` event to be emitted.
204
- - `ARIO.testnet().faucet.claimWithAuthToken({ authToken, recipient, quantity })` - claims tokens for the specified recipient address using the provided auth token.
205
- - `ARIO.testnet().faucet.verifyAuthToken({ authToken })` - verifies if the provided auth token is still valid.
206
-
207
- <details>
208
- <summary><i>Example client-side code for claiming tokens</i></summary>
209
-
210
- ```typescript
211
- import { ARIO } from '@ar.io/sdk';
212
-
213
- const testnet = ARIO.testnet();
214
- const captchaUrl = await ario.faucet.captchaUrl();
215
-
216
- // open the captcha URL in the browser, and listen for the auth token event
217
- const captchaWindow = window.open(
218
- captchaUrl.captchaUrl,
219
- '_blank',
220
- 'width=600,height=600',
221
- );
222
- /**
223
- * The captcha URL includes a window.parent.postMessage event that is used to send the auth token to the parent window.
224
- * You can store the auth token in localStorage and use it to claim tokens for the duration of the auth token's expiration (default 1 hour).
225
- */
226
- window.parent.addEventListener('message', async (event) => {
227
- if (event.data.type === 'ario-jwt-success') {
228
- localStorage.setItem('ario-jwt', event.data.token);
229
- localStorage.setItem('ario-jwt-expires-at', event.data.expiresAt);
230
- // close our captcha window
231
- captchaWindow?.close();
232
- // claim the tokens using the JWT token
233
- const res = await testnet.faucet
234
- .claimWithAuthToken({
235
- authToken: event.data.token,
236
- recipient: await window.arweaveWallet.getActiveAddress(),
237
- quantity: new ARIOToken(100).toMARIO().valueOf(), // 100 ARIO
238
- })
239
- .then((res) => {
240
- alert(
241
- 'Successfully claimed 100 ARIO tokens! Transaction ID: ' + res.id,
242
- );
243
- })
244
- .catch((err) => {
245
- alert(`Failed to claim tokens: ${err}`);
246
- });
247
- }
248
- });
249
-
250
- /**
251
- * Once you have a valid JWT, you can check if it is still valid and use it for subsequent requests without having to open the captcha again.
252
- */
253
- if (
254
- localStorage.getItem('ario-jwt-expires-at') &&
255
- Date.now() < parseInt(localStorage.getItem('ario-jwt-expires-at') ?? '0')
256
- ) {
257
- const res = await testnet.faucet.claimWithAuthToken({
258
- authToken: localStorage.getItem('ario-jwt') ?? '',
259
- recipient: await window.arweaveWallet.getActiveAddress(),
260
- quantity: new ARIOToken(100).toMARIO().valueOf(), // 100 ARIO
261
- });
262
- }
263
- ```
264
-
265
- </details>
266
-
267
- ## ARIO
164
+ ## ARIO Contract
268
165
 
269
166
  ### General
270
167
 
@@ -427,6 +324,108 @@ const { id: txId } = await ario.transfer(
427
324
  );
428
325
  ```
429
326
 
327
+ ### Networks
328
+
329
+ The SDK provides the following process IDs for the mainnet and testnet environments:
330
+
331
+ - `ARIO_MAINNET_PROCESS_ID` - Mainnet ARIO process ID (production)
332
+ - `ARIO_TESTNET_PROCESS_ID` - Testnet ARIO process ID (testing and development)
333
+ - `ARIO_DEVNET_PROCESS_ID` - Devnet ARIO process ID (development)
334
+
335
+ As of `v3.8.1` the SDK defaults all API interactions to **mainnet**. To use the **testnet** or **devnet** provide the appropriate `ARIO_TESTNET_PROCESS_ID` or `ARIO_DEVNET_PROCESS_ID` when initializing the client.
336
+
337
+ #### Mainnet
338
+
339
+ As of `v3.8.1` the SDK defaults all API interactions to **mainnet**. To use the **testnet** or **devnet** provide the appropriate `ARIO_TESTNET_PROCESS_ID` or `ARIO_DEVNET_PROCESS_ID` when initializing the client.
340
+
341
+ ```typescript
342
+ import { ARIO } from '@ar.io/sdk';
343
+
344
+ const ario = ARIO.mainnet(); // or ARIO.init()
345
+ ```
346
+
347
+ #### Testnet
348
+
349
+ ```typescript
350
+ import { ARIO } from '@ar.io/sdk';
351
+
352
+ const testnet = ARIO.testnet(); // or ARIO.init({ processId: ARIO_TESTNET_PROCESS_ID })
353
+ ```
354
+
355
+ ##### Faucet
356
+
357
+ The SDK provides APIs for claiming tokens via a faucet on the AR.IO Testnet process (`tARIO`) via the [ar-io-testnet-faucet] service. All token requests require a captcha to be solved, and the faucet is rate limited to prevent abuse.
358
+
359
+ To claim testnet tokens from the testnet token faucet, you can use one of the following methods:
360
+
361
+ 1. Visit [faucet.ar.io](https://faucet.ar.io) - the easiest way to quickly get tokens for testing for a single address.
362
+
363
+ 2. Programmatically via the SDK - useful if you need to claim tokens for multiple addresses or dynamically within your application.
364
+
365
+ - `ARIO.testnet().faucet.captchaUrl()` - returns the captcha URL for the testnet faucet. Open this URL in a new browser window and listen for the `ario-jwt-success` event to be emitted.
366
+ - `ARIO.testnet().faucet.claimWithAuthToken({ authToken, recipient, quantity })` - claims tokens for the specified recipient address using the provided auth token.
367
+ - `ARIO.testnet().faucet.verifyAuthToken({ authToken })` - verifies if the provided auth token is still valid.
368
+
369
+ <details>
370
+ <summary><i>Example client-side code for claiming tokens</i></summary>
371
+
372
+ ```typescript
373
+ import { ARIO } from '@ar.io/sdk';
374
+
375
+ const testnet = ARIO.testnet();
376
+ const captchaUrl = await ario.faucet.captchaUrl();
377
+
378
+ // open the captcha URL in the browser, and listen for the auth token event
379
+ const captchaWindow = window.open(
380
+ captchaUrl.captchaUrl,
381
+ '_blank',
382
+ 'width=600,height=600',
383
+ );
384
+ /**
385
+ * The captcha URL includes a window.parent.postMessage event that is used to send the auth token to the parent window.
386
+ * You can store the auth token in localStorage and use it to claim tokens for the duration of the auth token's expiration (default 1 hour).
387
+ */
388
+ window.parent.addEventListener('message', async (event) => {
389
+ if (event.data.type === 'ario-jwt-success') {
390
+ localStorage.setItem('ario-jwt', event.data.token);
391
+ localStorage.setItem('ario-jwt-expires-at', event.data.expiresAt);
392
+ // close our captcha window
393
+ captchaWindow?.close();
394
+ // claim the tokens using the JWT token
395
+ const res = await testnet.faucet
396
+ .claimWithAuthToken({
397
+ authToken: event.data.token,
398
+ recipient: await window.arweaveWallet.getActiveAddress(),
399
+ quantity: new ARIOToken(100).toMARIO().valueOf(), // 100 ARIO
400
+ })
401
+ .then((res) => {
402
+ alert(
403
+ 'Successfully claimed 100 ARIO tokens! Transaction ID: ' + res.id,
404
+ );
405
+ })
406
+ .catch((err) => {
407
+ alert(`Failed to claim tokens: ${err}`);
408
+ });
409
+ }
410
+ });
411
+
412
+ /**
413
+ * Once you have a valid JWT, you can check if it is still valid and use it for subsequent requests without having to open the captcha again.
414
+ */
415
+ if (
416
+ localStorage.getItem('ario-jwt-expires-at') &&
417
+ Date.now() < parseInt(localStorage.getItem('ario-jwt-expires-at') ?? '0')
418
+ ) {
419
+ const res = await testnet.faucet.claimWithAuthToken({
420
+ authToken: localStorage.getItem('ario-jwt') ?? '',
421
+ recipient: await window.arweaveWallet.getActiveAddress(),
422
+ quantity: new ARIOToken(100).toMARIO().valueOf(), // 100 ARIO
423
+ });
424
+ }
425
+ ```
426
+
427
+ </details>
428
+
430
429
  ### Vaults
431
430
 
432
431
  #### `getVault({ address, vaultId })`
@@ -2043,11 +2042,11 @@ const ario = ARIO.mainnet({
2043
2042
  });
2044
2043
  ```
2045
2044
 
2046
- ## Arweave Name Tokens (ANT's)
2045
+ ## ANT Contracts
2047
2046
 
2048
2047
  The ANT client class exposes APIs relevant to compliant Arweave Name Token processes. It can be configured to use any process ID that adheres to the ANT process spec. You must provide either a custom process data provider or a processId to the ANT class constructor to use.
2049
2048
 
2050
- ### ANT APIs
2049
+ ### Initialize
2051
2050
 
2052
2051
  #### `init({ processId, signer })`
2053
2052
 
@@ -2068,6 +2067,8 @@ const ant = ANT.init({
2068
2067
 
2069
2068
  ```
2070
2069
 
2070
+ ### Spawn
2071
+
2071
2072
  #### `spawn({ signer, module?, ao?, scheduler?, state?, antRegistryId?, logger?, authority? })`
2072
2073
 
2073
2074
  Spawns a new ANT (Arweave Name Token) process. This static function creates a new ANT process on the AO network and returns the process ID.
@@ -2122,9 +2123,11 @@ ar.io spawn-ant --wallet-file wallet.json --module FKtQtOOtlcWCW2pXrwWFiCSlnuewM
2122
2123
 
2123
2124
  **Returns:** `Promise<ProcessId>` - The process ID of the newly spawned ANT
2124
2125
 
2125
- #### `versions`
2126
+ ### Versions
2127
+
2128
+ #### `getANTVersions`
2126
2129
 
2127
- Returns an ANTVersions instance that provides access to available ANT versions from the ANT registry. This static property allows you to query version information without needing a specific ANT process.
2130
+ Returns the full array of available ANT versions and the latest version from the ANT registry.
2128
2131
 
2129
2132
  ```typescript
2130
2133
  import { ANT } from '@ar.io/sdk';
@@ -2132,12 +2135,47 @@ import { ANT } from '@ar.io/sdk';
2132
2135
  // Get all available ANT versions
2133
2136
  const antVersions = ANT.versions;
2134
2137
  const versions = await antVersions.getANTVersions();
2138
+ ```
2139
+
2140
+ Result:
2141
+
2142
+ ```json
2143
+ {
2144
+ [
2145
+ {
2146
+ "moduleId": "FKtQtOOtlcWCW2pXrwWFiCSlnuewMZOHCzhulVkyqBE",
2147
+ "version": "23",
2148
+ "releaseNotes": "Initial release of the ANT module.",
2149
+ "releaseDate": 1700000000000
2150
+ }
2151
+ // ...other versions
2152
+ ],
2153
+ }
2154
+ ```
2155
+
2156
+ #### `getLatestANTVersion()`
2157
+
2158
+ Returns the latest ANT version from the ANT registry.
2159
+
2160
+ ```typescript
2161
+ import { ANT } from '@ar.io/sdk';
2135
2162
 
2136
2163
  // Get the latest ANT version
2137
2164
  const latestVersion = await antVersions.getLatestANTVersion();
2138
2165
  ```
2139
2166
 
2140
- **Returns:** `AoANTVersionsRead` - A read-only ANT versions client
2167
+ Result:
2168
+
2169
+ ```json
2170
+ {
2171
+ "moduleId": "FKtQtOOtlcWCW2pXrwWFiCSlnuewMZOHCzhulVkyqBE",
2172
+ "version": "23",
2173
+ "releaseNotes": "Initial release of the ANT module.",
2174
+ "releaseDate": 1700000000000
2175
+ }
2176
+ ```
2177
+
2178
+ ### State
2141
2179
 
2142
2180
  #### `getInfo()`
2143
2181
 
@@ -2325,6 +2363,8 @@ const records = await ant.getRecords();
2325
2363
 
2326
2364
  </details>
2327
2365
 
2366
+ ### Transfer
2367
+
2328
2368
  #### `transfer({ target })`
2329
2369
 
2330
2370
  Transfers ownership of the ANT to a new target address. Target MUST be an Arweave address.
@@ -2339,6 +2379,8 @@ const { id: txId } = await ant.transfer(
2339
2379
  );
2340
2380
  ```
2341
2381
 
2382
+ ### Controllers
2383
+
2342
2384
  #### `setController({ controller })`
2343
2385
 
2344
2386
  Adds a new controller to the list of approved controllers on the ANT. Controllers can set records and change the ticker and name of the ANT process.
@@ -2367,6 +2409,8 @@ const { id: txId } = await ant.removeController(
2367
2409
  );
2368
2410
  ```
2369
2411
 
2412
+ ### Records
2413
+
2370
2414
  #### `setBaseNameRecord({ transactionId, ttlSeconds, owner?, displayName?, logo?, description?, keywords? })`
2371
2415
 
2372
2416
  Adds or updates the base name record for the ANT. This is the top level name of the ANT (e.g. ardrive.ar.io). Supports undername ownership delegation and metadata.
@@ -2500,6 +2544,8 @@ const { id: txId } = await ant.removeRecord(
2500
2544
  // dapp_ardrive.ar.io will no longer resolve to the provided transaction id
2501
2545
  ```
2502
2546
 
2547
+ ### Metadata
2548
+
2503
2549
  #### `setName({ name })`
2504
2550
 
2505
2551
  Sets the name of the ANT process.
@@ -2578,6 +2624,8 @@ const { id: txId } = await ant.setLogo(
2578
2624
  );
2579
2625
  ```
2580
2626
 
2627
+ ### ARIO Integrations
2628
+
2581
2629
  #### `releaseName({ name, arioProcessId })`
2582
2630
 
2583
2631
  Releases a name from the current owner and makes it available for purchase on the ARIO contract. The name must be permanently owned by the releasing wallet. If purchased within the recently returned name period (14 epochs), 50% of the purchase amount will be distributed to the ANT owner at the time of release. If no purchases in the recently returned name period, the name can be reregistered by anyone for the normal fee.
@@ -2633,6 +2681,8 @@ const { id: txId } = await ant.removePrimaryNames({
2633
2681
  });
2634
2682
  ```
2635
2683
 
2684
+ ### Upgrade
2685
+
2636
2686
  #### `upgrade({ reassignAffiliatedNames?, names?, arioProcessId?, antRegistryId?, skipVersionCheck?, onSigningProgress? })`
2637
2687
 
2638
2688
  Upgrades an ANT by forking it to the latest version from the ANT registry and optionally reassigning ArNS names to the new process. This function first checks the version of the existing ANT, creates a new ANT using `.fork()` to the latest version, and then reassigns the ArNS names affiliated with this process to the new process.
@@ -2685,6 +2735,17 @@ console.log(`Failed to reassign names: ${result.failedReassignedNames}`);
2685
2735
 
2686
2736
  **Returns:** `Promise<{ forkedProcessId: string, reassignedNames: Record<string, AoMessageResult>, failedReassignedNames: Record<string, { id?: string; error: Error }> }>`
2687
2737
 
2738
+ ### Undername Ownership
2739
+
2740
+ NTs support ownership of undernames:
2741
+
2742
+ 1. **ANT Owner** - Has full control over the ANT and all records
2743
+ 2. **Controllers** - Can manage records but cannot transfer ANT ownership
2744
+ 3. **Record Owners** - Can only update their specific delegated records
2745
+
2746
+ > [!WARNING]
2747
+ > When a record owner updates their own record, they **MUST** include their own address in the `owner` field. If the `owner` field is omitted or set to a different address, the record ownership will be transferred or renounced.
2748
+
2688
2749
  #### `transferRecord({ undername, recipient })`
2689
2750
 
2690
2751
  Transfers ownership of a specific record (undername) to another address. This enables delegation of control for individual records within an ANT while maintaining the ANT owner's ultimate authority. The current record owner or ANT owner/controllers can transfer ownership.
@@ -2712,26 +2773,6 @@ ar.io transfer-record \
2712
2773
  --wallet-file "path/to/wallet.json"
2713
2774
  ```
2714
2775
 
2715
- ### Understanding Record Ownership
2716
-
2717
- ANTs support ownership of undernames:
2718
-
2719
- 1. **ANT Owner** - Has full control over the ANT and all records
2720
- 2. **Controllers** - Can manage records but cannot transfer ANT ownership
2721
- 3. **Record Owners** - Can only update their specific delegated records
2722
-
2723
- **Record Owner Permissions:**
2724
-
2725
- - ✅ Update their own record's `transactionId`, `ttlSeconds`, and metadata
2726
- - ✅ Transfer ownership of their record to another address
2727
- - ❌ Modify other records in the ANT
2728
- - ❌ Add/remove controllers or transfer ANT ownership
2729
-
2730
- <!-- prettier-ignore-start -->
2731
- > [!CAUTION]
2732
- > **Important:** When a record owner updates their own record, they **MUST** include their own address in the `owner` field. If the `owner` field is omitted or set to a different address, the record ownership will be transferred or renounced.
2733
- <!-- prettier-ignore-end -->
2734
-
2735
2776
  #### Record Owner Workflow Examples
2736
2777
 
2737
2778
  **Checking Record Ownership:**
@@ -2800,33 +2841,13 @@ const recordAfter = await ant.getRecord({ undername: 'alice' });
2800
2841
  console.log(recordAfter.owner); // undefined (controlled by ANT owner again)
2801
2842
  ```
2802
2843
 
2803
- ### Configuration
2804
-
2805
- ANT clients can be configured to use custom AO process. Refer to [AO Connect] for more information on how to configure the AO process to use specific AO infrastructure.
2806
-
2807
- ```typescript
2808
-
2809
- const ant = ANT.init({
2810
- process: new AOProcess({
2811
- processId: 'ANT_PROCESS_ID'
2812
- ao: connect({
2813
- MODE: 'legacy',
2814
- MU_URL: 'https://mu-testnet.xyz',
2815
- CU_URL: 'https://cu-testnet.xyz',
2816
- GRAPHQL_URL: 'https://arweave.net/graphql',
2817
- GATEWAY_URL: 'https://arweave.net',
2818
- })
2819
- })
2820
- });
2821
- ```
2822
-
2823
2844
  ## Token Conversion
2824
2845
 
2825
2846
  The ARIO process stores all values as mARIO (milli-ARIO) to avoid floating-point arithmetic issues. The SDK provides an `ARIOToken` and `mARIOToken` classes to handle the conversion between ARIO and mARIO, along with rounding logic for precision.
2826
2847
 
2827
2848
  **All process interactions expect values in mARIO. If numbers are provided as inputs, they are assumed to be in raw mARIO values.**
2828
2849
 
2829
- ### Converting ARIO to mARIO
2850
+ #### Converting ARIO to mARIO
2830
2851
 
2831
2852
  ```typescript
2832
2853
  import { ARIOToken, mARIOToken } from '@ar.io/sdk';
@@ -2840,7 +2861,9 @@ const arioValue = new mARIOToken(mARIOValue).toARIO();
2840
2861
 
2841
2862
  ## Logging
2842
2863
 
2843
- The library uses the [Winston] logger for node based projects, and `console` logger for web based projects by default. You can configure the log level via `setLogLevel()` API. Alternatively you can set a custom logger as the default logger so long as it satisfes the `ILogger` interface.
2864
+ The library uses a lightweight console logger by default for both Node.js and web environments. The logger outputs structured JSON logs with timestamps. You can configure the log level via `setLogLevel()` API or provide a custom logger that satisfies the `ILogger` interface.
2865
+
2866
+ #### Default Logger
2844
2867
 
2845
2868
  ```typescript
2846
2869
  import { Logger } from '@ar.io/sdk';
@@ -2848,12 +2871,86 @@ import { Logger } from '@ar.io/sdk';
2848
2871
  // set the log level
2849
2872
  Logger.default.setLogLevel('debug');
2850
2873
 
2851
- // provide your own logger
2852
- Logger.default = winston.createLogger({ ...loggerConfigs }); // or some other logger that satisifes ILogger interface
2874
+ // Create a new logger instance with a specific level
2875
+ const logger = new Logger({ level: 'debug' });
2876
+ ```
2877
+
2878
+ #### Custom Logger Implementation
2879
+
2880
+ You can provide any custom logger that implements the `ILogger` interface:
2881
+
2882
+ ```typescript
2883
+ import { ARIO, ILogger } from '@ar.io/sdk';
2884
+
2885
+ // Custom logger example
2886
+ const customLogger: ILogger = {
2887
+ info: (message, ...args) => console.log(`[INFO] ${message}`, ...args),
2888
+ warn: (message, ...args) => console.warn(`[WARN] ${message}`, ...args),
2889
+ error: (message, ...args) => console.error(`[ERROR] ${message}`, ...args),
2890
+ debug: (message, ...args) => console.debug(`[DEBUG] ${message}`, ...args),
2891
+ setLogLevel: (level) => {
2892
+ /* implement level filtering */
2893
+ },
2894
+ };
2895
+
2896
+ // Use custom logger with any class
2897
+ const ario = ARIO.mainnet({ logger: customLogger });
2898
+
2899
+ // or set it as the default logger in the entire SDK
2900
+ Logger.default = customLogger;
2901
+ ```
2902
+
2903
+ #### Winston Logger (Optional)
2904
+
2905
+ For advanced logging features, you can optionally install Winston and use the provided Winston logger adapter:
2906
+
2907
+ ```bash
2908
+ yarn add winston
2909
+ ```
2910
+
2911
+ ```typescript
2912
+ import { ARIO, WinstonLogger } from '@ar.io/sdk';
2913
+
2914
+ // Create Winston logger with custom configuration
2915
+ const winstonLogger = new WinstonLogger({
2916
+ level: 'debug',
2917
+ });
2918
+
2919
+ // Use with any class that accepts a logger
2920
+ const ario = ARIO.mainnet({ logger: winstonLogger });
2921
+
2922
+ // or set it as the default logger in the entire SDK
2923
+ Logger.default = winstonLogger;
2924
+ ```
2925
+
2926
+ #### Other Popular Loggers
2927
+
2928
+ You can easily integrate other popular logging libraries:
2929
+
2930
+ ```typescript
2931
+ // Bunyan example
2932
+ import { ARIO, ILogger } from '@ar.io/sdk';
2933
+ import bunyan from 'bunyan';
2934
+
2935
+ const bunyanLogger = bunyan.createLogger({ name: 'ar-io-sdk' });
2936
+ const adapter: ILogger = {
2937
+ info: (message, ...args) => bunyanLogger.info({ args }, message),
2938
+ warn: (message, ...args) => bunyanLogger.warn({ args }, message),
2939
+ error: (message, ...args) => bunyanLogger.error({ args }, message),
2940
+ debug: (message, ...args) => bunyanLogger.debug({ args }, message),
2941
+ setLogLevel: (level) => bunyanLogger.level(level),
2942
+ };
2943
+
2944
+ const ario = ARIO.mainnet({ logger: adapter });
2945
+
2946
+ // or set it as the default logger in the entire SDK
2947
+ Logger.default = adapter;
2853
2948
  ```
2854
2949
 
2855
2950
  ## Pagination
2856
2951
 
2952
+ #### Overview
2953
+
2857
2954
  Certain APIs that could return a large amount of data are paginated using cursors. The SDK uses the `cursor` pattern (as opposed to pages) to better protect against changing data while paginating through a list of items. For more information on pagination strategies refer to [this article](https://www.getknit.dev/blog/api-pagination-best-practices#api-pagination-techniques-).
2858
2955
 
2859
2956
  Paginated results include the following properties:
@@ -2865,7 +2962,21 @@ Paginated results include the following properties:
2865
2962
  - `sortBy`: the field used to sort the items, by default this is `startTimestamp`.
2866
2963
  - `sortOrder`: the order used to sort the items, by default this is `desc`.
2867
2964
 
2868
- ### Filtering
2965
+ To request all the items in a list, you can iterate through the list using the `nextCursor` until `hasMore` is `false`.
2966
+
2967
+ ```typescript
2968
+ let hasMore = true;
2969
+ let cursor: string | undefined;
2970
+ const gateaways = [];
2971
+ while (hasMore) {
2972
+ const page = await ario.getGateways({ limit: 100, cursor });
2973
+ gateaways.push(...items);
2974
+ cursor = page.nextCursor;
2975
+ hasMore = page.hasMore;
2976
+ }
2977
+ ```
2978
+
2979
+ #### Filtering
2869
2980
 
2870
2981
  Paginated APIs also support filtering by providing a `filters` parameter. Filters can be applied to any field in the response. When multiple keys are provided, they are treated as AND conditions (all conditions must match). When multiple values are provided for a single key (as an array), they are treated as OR conditions (any value can match).
2871
2982
 
@@ -2888,22 +2999,6 @@ In the example above, the query will return ArNS records where:
2888
2999
  - The type is "lease" AND
2889
3000
  - The processId is EITHER "ZkgLfyHALs5koxzojpcsEFAKA8fbpzP7l-tbM7wmQNM" OR "r61rbOjyXx3u644nGl9bkwLWlWmArMEzQgxBo2R-Vu0"
2890
3001
 
2891
- ### Iterating Through Pages
2892
-
2893
- To request all the items in a list, you can iterate through the list using the `nextCursor` until `hasMore` is `false`.
2894
-
2895
- ```typescript
2896
- let hasMore = true;
2897
- let cursor: string | undefined;
2898
- const gateaways = [];
2899
- while (hasMore) {
2900
- const page = await ario.getGateways({ limit: 100, cursor });
2901
- gateaways.push(...items);
2902
- cursor = page.nextCursor;
2903
- hasMore = page.hasMore;
2904
- }
2905
- ```
2906
-
2907
3002
  ## Resources
2908
3003
 
2909
3004
  ### Bundling
@@ -2985,3 +3080,7 @@ For more information on how to contribute, please see [CONTRIBUTING.md].
2985
3080
  [ar.io Gateway Documentation]: https://docs.ar.io/gateways/ar-io-node/overview/
2986
3081
  [ANS-104]: https://github.com/ArweaveTeam/arweave-standards/blob/master/ans/ANS-104.md
2987
3082
  [ar-io-testnet-faucet]: https://github.com/ar-io/ar-io-testnet-faucet?tab=readme-ov-file#asynchronous-workflow
3083
+
3084
+ ```
3085
+
3086
+ ```