npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@gibwork/sdk

v0.2.0

Published

TypeScript SDK for the Gibwork External API

Readme

Gibwork SDK

TypeScript SDK for the wallet-authenticated Gibwork External API.

It handles wallet addresses, nonces, timestamps, payload normalization, message signatures, HTTP requests, and Solana transaction signing for you.

Installation

The package is currently private while its npm name and license are finalized. Once published:

npm install @gibwork/sdk

Requires Node.js 22 or newer.

Quick start

Load your environment variables in the application, then pass the private key to the Node entry point. The SDK never loads .env implicitly.

SOLANA_PRIVATE_KEY=[1,2,3,...]
import { createGibworkClient } from '@gibwork/sdk/node';

const gibwork = createGibworkClient({
  privateKey: process.env.SOLANA_PRIVATE_KEY!,
  production: true,
});

Requests use the stage environment by default. Set production: true when creating the client to route all of its requests to production. The setting is client-wide, so prepare and transaction-submit requests always use the same environment.

SOLANA_PRIVATE_KEY may be a base58-encoded 32-byte seed or 64-byte secret key, or a JSON array containing 32 or 64 byte values.

Applications using a wallet adapter or custom custody provider can inject a signer instead:

import { GibworkClient, type WalletSigner } from '@gibwork/sdk';

declare const signer: WalletSigner;

const gibwork = new GibworkClient({
  signer,
  production: true,
});

Methods

const task = await gibwork.tasks.create({
  title: 'Write an SDK guide',
  content: '<p>Document the Gibwork SDK.</p>',
  tags: ['Docs'],
  payment: {
    mintAddress: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
    amount: '25.00',
  },
  minSubmissionAmount: '5.00',
});

const tasks = await gibwork.tasks.list();
const taskDetails = await gibwork.tasks.get(task.taskId);
console.log(taskDetails.content);
const updatedTask = await gibwork.tasks.update(task.taskId, {
  content: '<p>Updated bounty instructions.</p>',
  allowOnlyVerifiedSubmissions: true,
  deadline: '2026-10-01T12:00:00.000Z',
});
const submissions = await gibwork.submissions.list(task.taskId);

await gibwork.submissions.approve(task.taskId, submissionId, {
  amount: '5.00',
  rating: 5,
});

await gibwork.submissions.reject(
  task.taskId,
  submissionId,
  'Please include the source files.',
);

const comments = await gibwork.submissions.comments.list(
  task.taskId,
  submissionId,
);
await gibwork.submissions.comments.create(
  task.taskId,
  submissionId,
  'Thanks for the update.',
);

await gibwork.tasks.refund(task.taskId);

tasks.update changes metadata on an open bounty created by the signing wallet. It can update content, allowOnlyVerifiedSubmissions, and deadline, and it does not create or sign a Solana transaction. Deadline updates may be ignored by the API for non-credit bounties worth less than $5 USD.

tasks.create, tasks.refund, and submissions.approve perform the complete prepare, sign, and submit sequence. Advanced callers can control the phases with:

  • tasks.prepareCreate and tasks.submitCreate
  • tasks.prepareRefund and tasks.submitRefund
  • submissions.prepareApproval and submissions.submitApproval
  • signPreparedTransaction

All request methods accept an optional final { signal } argument for cancellation. Set the default request timeout with timeoutMs when creating the client.

Discover tasks and submit work

const available = await gibwork.tasks.listAvailable({ page: 1, limit: 15 });

// Persist the key and exact input before sending. Supply your own UUIDv4.
const input = {
  content: '<p>Completed work: https://example.com/work</p>',
  idempotencyKey: savedIdempotencyKey,
};
const intent = await gibwork.submissions.create(taskId, input);

if (intent.status === 'submitted') {
  const current = await gibwork.submissions.getIntent(taskId, intent.intentId);
}

Discovery is free and wallet-authenticated across creators; tasks.list lists created tasks, while tasks.get(taskId) returns one bounty's complete content, reward, creator, media, and participation settings whether or not it appears on the current discovery page. Discovery accepts only page and limit (defaults 1/15, maximum limit 100). Results show eligibility requirements, not a guarantee that your wallet can submit. asset.amount and minSubmissionAmount are strings in base units; the asset amount is the original reward pool, not remaining funds.

Submitting work requires an active platform wallet, eligibility, and currently 0.15 USDC. Network costs are sponsored. Read the returned fee for amounts. Optional referral and mediaIds are supported; media must already be uploaded and owned by the caller. The SDK preserves submission content/referral exactly when signing, including whitespace and HTML.

For separate phases use:

  • submissions.prepareCreate(taskId, input)
  • signPreparedTransaction(prepared.serializedTransaction, signer)
  • submissions.submitCreate(taskId, intentId, { paymentAttemptId, signedTransaction })
  • submissions.getIntent(taskId, intentId)

Prepare can return an existing intent without a transaction. submissions.create signs only a pending intent with a transaction and returns the state after one submit; it does not poll or retry automatically.

| State | Meaning and recovery | | -------------------- | -------------------------------------------------------------------------------------- | | pending | Not submitted. Retry prepare with the original input/key to obtain the transaction. | | submitted | Unresolved. Read the same intent later. | | fulfilled | Fee confirmed and submission created. | | failed / expired | Resolve the attempt before explicitly choosing a new key. | | requires_review | Fee paid; operator attention required. Retain the intent ID/hash and do not pay again. |

Only fulfilled confirms creation. taskSubmissionId is allocated in advance; its presence and HTTP 200 alone do not prove success. Intent status does not report subsequent creator review/payout, and existing creator submission reads have not been extended to participants.

After an interrupted prepare, reuse the exact input/key with the same wallet and environment. After an uncertain submit, use getIntent with the original wallet, including after wallet replacement. Each call generates fresh auth. The same key still returns the original intent after failure/expiry. A 409 error may contain an existing intent ID in its structured body.

The upstream wallet limits are discovery 30/minute, prepare 2/minute, submit 5/minute, and status 60/minute. Respect GibworkApiError.retryAfter (seconds or an HTTP date) before another request; it is optional. The stage example persists recovery data before payment and uses explicit status reads on later invocations:

npm run build
node --env-file=.env examples/create-submission.mjs work.json recovery.json

work.json contains { "taskId": "UUID", "input": { "content": "...", "idempotencyKey": "UUIDv4" } }. This example may charge the stage participation fee. Once it records an intent, rerunning only reads status. No media upload or operator resolution endpoint is provided by this SDK.

Errors

API failures throw GibworkApiError with status and the parsed response body, plus optional requestId and raw retryAfter. Network failures and timeouts use typed SDK errors.

Transaction submits are never retried automatically. If the network or server fails while submitting, the SDK throws GibworkAmbiguousSubmitError with safe task, submission, and intent identifiers. Do not resubmit the same intent blindly.

GibworkValidationError reports invalid discovery/submission input before a request. GibworkProtocolError reports an unusable intent response. The submissions.create convenience method wraps non-ambiguous failures in GibworkSubmissionOperationError: context retains the phase, original idempotency key, wallet/environment/API location, and intent identifiers when known; cause retains the original typed error. Ambiguous payments remain GibworkAmbiguousSubmitError with enriched context. A wallet rejection or cancellation before dispatch is not classified as a broadcast payment.

Development

npm install
npm run check

The package currently remains UNLICENSED; select and add the intended public license before treating the release as generally reusable open-source software.

Private-key safety

The SDK never transmits the private key, loads .env implicitly, or includes key material in its errors. Never expose the Node private-key entry point in a browser bundle. Browser consumers should provide a wallet-adapter-backed signer.