Typescript example

Simple example of how to consume our API in a typescript code base. Please use this as a starting point.

We recommend making use of runtime validation libraries such as zod or pydantic.

const max_time = 30 * 1000; //Cut the stream after 30s

async function callOCI(wallet: string): Promise<ModuleResponse[]> {
  const key = process.env.OCI_API_KEY;

  if (!key)
    throw new Error(
      'OCI API Key undefined, did you forget to update your .env?'
    );

  const controller = new AbortController();

  const platforms: ModuleResponse[] = [];

  const oci_call = fetch('https://api.onchain.industries/beta/query-one', {
    signal: controller.signal,
    method: 'POST',
    body: JSON.stringify({
      query: wallet, //You could search usernames as well.
    }),
    headers: {
      'Content-Type': 'application/json',
      key: key,
    },
  })
    .then(async (response) => {
      if (response.ok === false) {
        console.error('🚨 Response was not ok.', response.headers);
        return;
      }

      if (!response.body) {
        console.error('🚨 Response had no body.', response.headers);
        return;
      }

      const reader = response.body.getReader();

      if (!reader) {
        console.error('🚨 Could not append reader to response.');
        return;
      }

      let buffer: string[] = [];

      function flushBuffer() {
        if (buffer.length === 0) return;

        const chunk = buffer.join('');

        try {
          platforms.push(JSON.parse(chunk));
        } catch (error) {
          console.warn('🚨 Could not parse chunks in buffer');
          console.error(error);
        } finally {
          buffer = [];
        }
      }

      while (true) {
        const { done, value } = await reader.read();

        if (done) {
          console.log('Stream is done');
          break;
        }

        const chunk = new TextDecoder().decode(value);

        try {
          platforms.push(JSON.parse(chunk));
          if (queue.length > 0) {
            flushBuffer();
          }
        } catch (error) {
          //Prob the chunk was too big, lets added it our buffer
          queue.push(chunk);
          continue;
        }
      }
    })
    .catch((error) => {
      console.warn('🚨 Time probably ran out.');
      console.error(error);
    });

  const timer = new Promise((resolved) => {
    const timer = setTimeout(() => {
      controller.abort();
      resolved({});
    }, max_time);

    oci_call.finally(() => clearTimeout(timer));
  });

  await Promise.race([oci_call, timer]);

  return platforms;
}
type ModuleResponse = {
  search_type: string;
  version: string;
  status: string;
  data_type: {
    label: string;
    description: string;
  };
  platform: {
    name: string;
    url: string;
    description?: string;
    attributes: Array<{
      name: string;
      value: string;
    }>;
  };
  data: {
    exists: boolean | 'unknown';
    profile_url: string | null;
    // For details on the shape, visit our platforms section.
    original: Record<string, unknown> | Array<Record<string, unknown>[]> | null;
    data: null | Partial<{
      account_url?: string | null;
      joined: Date | null;
      updated: Date | null;
      followers: number | null;
      following: number | null;
      bio: string | null;
      emails: Array<{ address: string; tags?: string[] }> | null;
      usernames: Array<{ username: string; tags: string[] | null }> | null;
      names: Array<{ name: string; tags?: string[] }> | null;
      wallets: Array<{ address: string; tags?: string[] }> | null;
      ids: Array<{ id: string; tags?: string[] }> | null;
      ens: Array<{ ens: string; tags: string[] }> | null;
      links: Array<{ url: string; tags: string[] | null }> | null;
      images_url: Array<{ url: string; tags: string[] | null }> | null;
      transactions: Array<{ txn_hash: string; tags?: string[] }> | null;
      nfts: Array<{
        label: string;
        url: string;
        address: string;
        chain: string;
        tags: string[] | null;
      }>;
      linked_accounts: Array<{
        platform: string;
        profile_url: string | null;
        username: string | null;
      }> | null;
      soft_links: Array<{
        data: string;
        data_type: string;
        relationship: string;
      }> | null;
      /** Any field that doesn't fit into the defined schema. */
      dynamic: Array<{
        name: string;
        value: any;
        description: string | null;
      }> | null;
    }>;
    obfuscated_data: null | Partial<{
      wallets: Array<{ count: number; items?: string[] }>;
      usernames: Array<{ count: number; items?: string[] }>;
      links: Array<{ count: number; items?: string[] }>;
      relative_links: Array<{ count: number; items?: string[] }>;
      emails: Array<{ count: number; items?: string[] }>;
      ip_addresses: Array<{ count: number; items?: string[] }>;
    }>;
  };
  error?: string;
};