diff --git a/.stats.yml b/.stats.yml index 704584e..b864056 100755 --- a/.stats.yml +++ b/.stats.yml @@ -1,2 +1,2 @@ configured_endpoints: 19 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/new%2Fblockaid-5e4d0576b2d38134571cb327258a600c25f8caa892fe15739b0c6dd6f0af182c.yml +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/new%2Fblockaid-d12231e708d72c768cb8fbda6c19928542f3f854c6e916c1cfb27b50885cfff2.yml diff --git a/README.md b/README.md index 92d9d57..780cc07 100755 --- a/README.md +++ b/README.md @@ -22,7 +22,9 @@ The full API of this library can be found in [api.md](api.md). ```js import Blockaid from '@blockaid/client'; -const client = new Blockaid(); +const client = new Blockaid({ + environment: 'direct', // defaults to 'production' +}); async function main() { const transactionScanResponse = await client.evm.jsonRpc.scan({ @@ -51,7 +53,9 @@ This library includes TypeScript definitions for all request params and response ```ts import Blockaid from '@blockaid/client'; -const client = new Blockaid(); +const client = new Blockaid({ + environment: 'direct', // defaults to 'production' +}); async function main() { const params: Blockaid.Evm.JsonRpcScanParams = { @@ -134,7 +138,6 @@ You can use the `maxRetries` option to configure or disable this: // Configure the default for all requests: const client = new Blockaid({ maxRetries: 0, // default is 2 - apiKey: 'My API Key', }); // Or, configure per-request: @@ -152,7 +155,6 @@ Requests time out after 1 minute by default. You can configure this with a `time // Configure the default for all requests: const client = new Blockaid({ timeout: 20 * 1000, // 20 seconds (default is 1 minute) - apiKey: 'My API Key', }); // Override per-request: @@ -308,7 +310,6 @@ import { HttpsProxyAgent } from 'https-proxy-agent'; // Configure the default for all requests: const client = new Blockaid({ httpAgent: new HttpsProxyAgent(process.env.PROXY_URL), - apiKey: 'My API Key', }); // Override per-request: diff --git a/src/index.ts b/src/index.ts index 8823b38..facacb7 100755 --- a/src/index.ts +++ b/src/index.ts @@ -6,11 +6,31 @@ import { type Agent } from './_shims/index'; import * as Core from './core'; import * as API from './resources/index'; +const environments = { + production: 'https://api.blockaid.io', + direct: 'https://direct.api.blockaid.io', +}; +type Environment = keyof typeof environments; + export interface ClientOptions { /** - * Defaults to process.env['BLOCKAID_CLIENT_API_KEY']. + * Authentication method to api.blockaid.io + */ + apiKey?: string | null | undefined; + + /** + * Authentication method to direct.api.blockaid.io + */ + clientId?: string | null | undefined; + + /** + * Specifies the environment to use for the API. + * + * Each environment maps to a different base URL: + * - `production` corresponds to `https://api.blockaid.io` + * - `direct` corresponds to `https://direct.api.blockaid.io` */ - apiKey?: string | undefined; + environment?: Environment; /** * Override the default base URL for the API, e.g., "https://api.example.com/v2/" @@ -73,14 +93,17 @@ export interface ClientOptions { * API Client for interfacing with the Blockaid API. */ export class Blockaid extends Core.APIClient { - apiKey: string; + apiKey: string | null; + clientId: string | null; private _options: ClientOptions; /** * API Client for interfacing with the Blockaid API. * - * @param {string | undefined} [opts.apiKey=process.env['BLOCKAID_CLIENT_API_KEY'] ?? undefined] + * @param {string | null | undefined} [opts.apiKey=process.env['BLOCKAID_CLIENT_API_KEY'] ?? null] + * @param {string | null | undefined} [opts.clientId=process.env['BLOCKAID_CLIENT_ID_KEY'] ?? null] + * @param {Environment} [opts.environment=production] - Specifies the environment URL to use for the API. * @param {string} [opts.baseURL=process.env['BLOCKAID_BASE_URL'] ?? https://api.blockaid.io] - Override the default base URL for the API. * @param {number} [opts.timeout=1 minute] - The maximum amount of time (in milliseconds) the client will wait for a response before timing out. * @param {number} [opts.httpAgent] - An HTTP agent used to manage HTTP(s) connections. @@ -91,23 +114,26 @@ export class Blockaid extends Core.APIClient { */ constructor({ baseURL = Core.readEnv('BLOCKAID_BASE_URL'), - apiKey = Core.readEnv('BLOCKAID_CLIENT_API_KEY'), + apiKey = Core.readEnv('BLOCKAID_CLIENT_API_KEY') ?? null, + clientId = Core.readEnv('BLOCKAID_CLIENT_ID_KEY') ?? null, ...opts }: ClientOptions = {}) { - if (apiKey === undefined) { - throw new Errors.BlockaidError( - "The BLOCKAID_CLIENT_API_KEY environment variable is missing or empty; either provide it, or instantiate the Blockaid client with an apiKey option, like new Blockaid({ apiKey: 'My API Key' }).", - ); - } - const options: ClientOptions = { apiKey, + clientId, ...opts, - baseURL: baseURL || `https://api.blockaid.io`, + baseURL, + environment: opts.environment ?? 'production', }; + if (baseURL && opts.environment) { + throw new Errors.BlockaidError( + 'Ambiguous URL; The `baseURL` option (or BLOCKAID_BASE_URL env var) and the `environment` option are given. If you want to use the environment you must pass baseURL: null', + ); + } + super({ - baseURL: options.baseURL!, + baseURL: options.baseURL || environments[options.environment || 'production'], timeout: options.timeout ?? 60000 /* 1 minute */, httpAgent: options.httpAgent, maxRetries: options.maxRetries, @@ -117,6 +143,7 @@ export class Blockaid extends Core.APIClient { this._options = options; this.apiKey = apiKey; + this.clientId = clientId; } evm: API.Evm = new API.Evm(this); diff --git a/tests/api-resources/bitcoin/transaction.test.ts b/tests/api-resources/bitcoin/transaction.test.ts index 8327e29..7ed00a0 100755 --- a/tests/api-resources/bitcoin/transaction.test.ts +++ b/tests/api-resources/bitcoin/transaction.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource transaction', () => { test('scan: only required params', async () => { diff --git a/tests/api-resources/evm/json-rpc.test.ts b/tests/api-resources/evm/json-rpc.test.ts index 61c28a1..e50d4da 100755 --- a/tests/api-resources/evm/json-rpc.test.ts +++ b/tests/api-resources/evm/json-rpc.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource jsonRpc', () => { test('scan: only required params', async () => { diff --git a/tests/api-resources/evm/post-transaction-bulk.test.ts b/tests/api-resources/evm/post-transaction-bulk.test.ts index 040c2db..583a34a 100755 --- a/tests/api-resources/evm/post-transaction-bulk.test.ts +++ b/tests/api-resources/evm/post-transaction-bulk.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource postTransactionBulk', () => { test('scan: only required params', async () => { diff --git a/tests/api-resources/evm/post-transaction.test.ts b/tests/api-resources/evm/post-transaction.test.ts index 931a422..166688f 100755 --- a/tests/api-resources/evm/post-transaction.test.ts +++ b/tests/api-resources/evm/post-transaction.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource postTransaction', () => { test('report: only required params', async () => { diff --git a/tests/api-resources/evm/transaction-bulk.test.ts b/tests/api-resources/evm/transaction-bulk.test.ts index 999d431..f44a977 100755 --- a/tests/api-resources/evm/transaction-bulk.test.ts +++ b/tests/api-resources/evm/transaction-bulk.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource transactionBulk', () => { test('scan: only required params', async () => { diff --git a/tests/api-resources/evm/transaction-raw.test.ts b/tests/api-resources/evm/transaction-raw.test.ts index 3fc635f..06230c7 100755 --- a/tests/api-resources/evm/transaction-raw.test.ts +++ b/tests/api-resources/evm/transaction-raw.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource transactionRaw', () => { test('scan: only required params', async () => { diff --git a/tests/api-resources/evm/transaction.test.ts b/tests/api-resources/evm/transaction.test.ts index fba977f..46dcb7d 100755 --- a/tests/api-resources/evm/transaction.test.ts +++ b/tests/api-resources/evm/transaction.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource transaction', () => { test('report: only required params', async () => { diff --git a/tests/api-resources/evm/user-operation.test.ts b/tests/api-resources/evm/user-operation.test.ts index 0dac026..8a0293e 100755 --- a/tests/api-resources/evm/user-operation.test.ts +++ b/tests/api-resources/evm/user-operation.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource userOperation', () => { test('scan: only required params', async () => { diff --git a/tests/api-resources/site.test.ts b/tests/api-resources/site.test.ts index e9b4349..182fa66 100755 --- a/tests/api-resources/site.test.ts +++ b/tests/api-resources/site.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource site', () => { test('report: only required params', async () => { diff --git a/tests/api-resources/solana/address.test.ts b/tests/api-resources/solana/address.test.ts index b81f737..bb7c323 100755 --- a/tests/api-resources/solana/address.test.ts +++ b/tests/api-resources/solana/address.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource address', () => { test('scan: only required params', async () => { diff --git a/tests/api-resources/solana/message.test.ts b/tests/api-resources/solana/message.test.ts index 4c25484..7925f72 100755 --- a/tests/api-resources/solana/message.test.ts +++ b/tests/api-resources/solana/message.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource message', () => { test('scan: only required params', async () => { diff --git a/tests/api-resources/starknet/transaction.test.ts b/tests/api-resources/starknet/transaction.test.ts index 9317722..a6cbd90 100755 --- a/tests/api-resources/starknet/transaction.test.ts +++ b/tests/api-resources/starknet/transaction.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource transaction', () => { test('scan: only required params', async () => { diff --git a/tests/api-resources/stellar/transaction.test.ts b/tests/api-resources/stellar/transaction.test.ts index 529fd3d..97e4a09 100755 --- a/tests/api-resources/stellar/transaction.test.ts +++ b/tests/api-resources/stellar/transaction.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource transaction', () => { test('scan: only required params', async () => { diff --git a/tests/api-resources/token-bulk.test.ts b/tests/api-resources/token-bulk.test.ts index 3b64453..1efc843 100755 --- a/tests/api-resources/token-bulk.test.ts +++ b/tests/api-resources/token-bulk.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource tokenBulk', () => { test('scan: only required params', async () => { diff --git a/tests/api-resources/token.test.ts b/tests/api-resources/token.test.ts index 502d6a3..0977320 100755 --- a/tests/api-resources/token.test.ts +++ b/tests/api-resources/token.test.ts @@ -3,10 +3,7 @@ import Blockaid from '@blockaid/client'; import { Response } from 'node-fetch'; -const client = new Blockaid({ - apiKey: 'My API Key', - baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', -}); +const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010' }); describe('resource token', () => { test('report: only required params', async () => { diff --git a/tests/index.test.ts b/tests/index.test.ts index 7825945..2018dec 100755 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -23,7 +23,6 @@ describe('instantiate client', () => { const client = new Blockaid({ baseURL: 'http://localhost:5000/', defaultHeaders: { 'X-My-Default-Header': '2' }, - apiKey: 'My API Key', }); test('they are used in the request', () => { @@ -52,11 +51,7 @@ describe('instantiate client', () => { describe('defaultQuery', () => { test('with null query params given', () => { - const client = new Blockaid({ - baseURL: 'http://localhost:5000/', - defaultQuery: { apiVersion: 'foo' }, - apiKey: 'My API Key', - }); + const client = new Blockaid({ baseURL: 'http://localhost:5000/', defaultQuery: { apiVersion: 'foo' } }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo'); }); @@ -64,17 +59,12 @@ describe('instantiate client', () => { const client = new Blockaid({ baseURL: 'http://localhost:5000/', defaultQuery: { apiVersion: 'foo', hello: 'world' }, - apiKey: 'My API Key', }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/foo?apiVersion=foo&hello=world'); }); test('overriding with `undefined`', () => { - const client = new Blockaid({ - baseURL: 'http://localhost:5000/', - defaultQuery: { hello: 'world' }, - apiKey: 'My API Key', - }); + const client = new Blockaid({ baseURL: 'http://localhost:5000/', defaultQuery: { hello: 'world' } }); expect(client.buildURL('/foo', { hello: undefined })).toEqual('http://localhost:5000/foo'); }); }); @@ -82,7 +72,6 @@ describe('instantiate client', () => { test('custom fetch', async () => { const client = new Blockaid({ baseURL: 'http://localhost:5000/', - apiKey: 'My API Key', fetch: (url) => { return Promise.resolve( new Response(JSON.stringify({ url, custom: true }), { @@ -99,7 +88,6 @@ describe('instantiate client', () => { test('custom signal', async () => { const client = new Blockaid({ baseURL: process.env['TEST_API_BASE_URL'] ?? 'http://127.0.0.1:4010', - apiKey: 'My API Key', fetch: (...args) => { return new Promise((resolve, reject) => setTimeout( @@ -124,12 +112,12 @@ describe('instantiate client', () => { describe('baseUrl', () => { test('trailing slash', () => { - const client = new Blockaid({ baseURL: 'http://localhost:5000/custom/path/', apiKey: 'My API Key' }); + const client = new Blockaid({ baseURL: 'http://localhost:5000/custom/path/' }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); }); test('no trailing slash', () => { - const client = new Blockaid({ baseURL: 'http://localhost:5000/custom/path', apiKey: 'My API Key' }); + const client = new Blockaid({ baseURL: 'http://localhost:5000/custom/path' }); expect(client.buildURL('/foo', null)).toEqual('http://localhost:5000/custom/path/foo'); }); @@ -138,55 +126,52 @@ describe('instantiate client', () => { }); test('explicit option', () => { - const client = new Blockaid({ baseURL: 'https://example.com', apiKey: 'My API Key' }); + const client = new Blockaid({ baseURL: 'https://example.com' }); expect(client.baseURL).toEqual('https://example.com'); }); test('env variable', () => { process.env['BLOCKAID_BASE_URL'] = 'https://example.com/from_env'; - const client = new Blockaid({ apiKey: 'My API Key' }); + const client = new Blockaid({}); expect(client.baseURL).toEqual('https://example.com/from_env'); }); test('empty env variable', () => { process.env['BLOCKAID_BASE_URL'] = ''; // empty - const client = new Blockaid({ apiKey: 'My API Key' }); + const client = new Blockaid({}); expect(client.baseURL).toEqual('https://api.blockaid.io'); }); test('blank env variable', () => { process.env['BLOCKAID_BASE_URL'] = ' '; // blank - const client = new Blockaid({ apiKey: 'My API Key' }); + const client = new Blockaid({}); + expect(client.baseURL).toEqual('https://api.blockaid.io'); + }); + + test('env variable with environment', () => { + process.env['BLOCKAID_BASE_URL'] = 'https://example.com/from_env'; + + expect(() => new Blockaid({ environment: 'production' })).toThrowErrorMatchingInlineSnapshot( + `"Ambiguous URL; The \`baseURL\` option (or BLOCKAID_BASE_URL env var) and the \`environment\` option are given. If you want to use the environment you must pass baseURL: null"`, + ); + + const client = new Blockaid({ baseURL: null, environment: 'production' }); expect(client.baseURL).toEqual('https://api.blockaid.io'); }); }); test('maxRetries option is correctly set', () => { - const client = new Blockaid({ maxRetries: 4, apiKey: 'My API Key' }); + const client = new Blockaid({ maxRetries: 4 }); expect(client.maxRetries).toEqual(4); // default - const client2 = new Blockaid({ apiKey: 'My API Key' }); + const client2 = new Blockaid({}); expect(client2.maxRetries).toEqual(2); }); - - test('with environment variable arguments', () => { - // set options via env var - process.env['BLOCKAID_CLIENT_API_KEY'] = 'My API Key'; - const client = new Blockaid(); - expect(client.apiKey).toBe('My API Key'); - }); - - test('with overriden environment variable arguments', () => { - // set options via env var - process.env['BLOCKAID_CLIENT_API_KEY'] = 'another My API Key'; - const client = new Blockaid({ apiKey: 'My API Key' }); - expect(client.apiKey).toBe('My API Key'); - }); }); describe('request building', () => { - const client = new Blockaid({ apiKey: 'My API Key' }); + const client = new Blockaid({}); describe('Content-Length', () => { test('handles multi-byte characters', () => { @@ -228,7 +213,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Blockaid({ apiKey: 'My API Key', timeout: 10, fetch: testFetch }); + const client = new Blockaid({ timeout: 10, fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); @@ -255,7 +240,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Blockaid({ apiKey: 'My API Key', fetch: testFetch }); + const client = new Blockaid({ fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2); @@ -282,7 +267,7 @@ describe('retries', () => { return new Response(JSON.stringify({ a: 1 }), { headers: { 'Content-Type': 'application/json' } }); }; - const client = new Blockaid({ apiKey: 'My API Key', fetch: testFetch }); + const client = new Blockaid({ fetch: testFetch }); expect(await client.request({ path: '/foo', method: 'get' })).toEqual({ a: 1 }); expect(count).toEqual(2);