Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add faucet and other utils #5

Merged
merged 7 commits into from
Nov 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified bun.lockb
Binary file not shown.
24 changes: 6 additions & 18 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,9 @@
import {
accounts,
blocks,
info,
proofOfTransfer,
smartContracts,
stackingPool,
transactions,
} from "./stacks-api/index.js";
export const stacksApi = {
accounts,
blocks,
info,
proofOfTransfer,
smartContracts,
stackingPool,
transactions,
};
export { stacksApi } from "./stacks-api/index.js";
export type * as StacksApi from "./stacks-api/index.js";

export { stacksRpcApi } from "./stacks-rpc-api/index.js";
export type * as StacksRpcApi from "./stacks-rpc-api/index.js";

export { queries } from "./queries/index.js";

export * from "./utils/index.js";
9 changes: 7 additions & 2 deletions src/stacks-api/accounts/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
export { balances } from "./balances.js";
import { balances } from "./balances.js";
export type * as Balances from "./balances.js";

export { latestNonce } from "./latest-nonce.js";
import { latestNonce } from "./latest-nonce.js";
export type * as LatestNonce from "./latest-nonce.js";

export const accounts = {
balances,
latestNonce,
};
6 changes: 5 additions & 1 deletion src/stacks-api/blocks/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
export { getBlock } from "./get-block.js";
import { getBlock } from "./get-block.js";
export type * as GetBlock from "./get-block.js";

export const blocks = {
getBlock,
};
6 changes: 6 additions & 0 deletions src/stacks-api/faucets/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { stx } from "./stx.js";
export type * as Stx from "./stx.js";

export const faucets = {
stx,
};
47 changes: 47 additions & 0 deletions src/stacks-api/faucets/stx.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { error, safePromise, success, type Result } from "../../utils/safe.js";
import type { ApiRequestOptions } from "../types.js";

export type Args = {
address: string;
stacking?: boolean;
} & ApiRequestOptions;

export async function stx(opts: Args): Promise<Result<any>> {
const search = new URLSearchParams();
search.append("address", opts.address);
if (opts.stacking) search.append("stacking", "true");

const init: RequestInit = {};
if (opts.apiKeyConfig) {
init.headers = {
[opts.apiKeyConfig.header]: opts.apiKeyConfig.key,
};
}
init.method = "POST";

const endpoint = `${opts.baseUrl}/extended/v1/faucets/stx?${search}`;
const res = await fetch(endpoint, init);

if (!res.ok) {
return error({
name: "FetchStxError",
message: "Failed to fetch STX.",
data: {
status: res.status,
statusText: res.statusText,
bodyParseResult: await safePromise(res.json()),
},
});
}

const [jsonError, data] = await safePromise(res.json());
if (jsonError) {
return error({
name: "ParseBodyError",
message: "Failed to parse response body as JSON.",
data: jsonError,
});
}

return success(data);
}
47 changes: 19 additions & 28 deletions src/stacks-api/index.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,30 @@
import { balances, latestNonce } from "./accounts/index.js";
export const accounts = { balances, latestNonce };
import { accounts } from "./accounts/index.js";
export type * as Accounts from "./accounts/index.js";

import { getBlock } from "./blocks/index.js";
export const blocks = { getBlock };
import { blocks } from "./blocks/index.js";
export type * as Blocks from "./blocks/index.js";

import { coreApi, poxDetails } from "./info/index.js";
export const info = { coreApi, poxDetails };
import { faucets } from "./faucets/index.js";
export type * as Faucets from "./faucets/index.js";

import { info } from "./info/index.js";
export type * as Info from "./info/index.js";

import {
cycle,
cycles,
signerInCycle,
signersInCycle,
stackersForSignerInCycle,
} from "./proof-of-transfer/index.js";
export const proofOfTransfer = {
cycle,
cycles,
signerInCycle,
signersInCycle,
stackersForSignerInCycle,
};
import { proofOfTransfer } from "./proof-of-transfer/index.js";
export type * as ProofOfTransfer from "./proof-of-transfer/index.js";

import { readOnly } from "./smart-contracts/index.js";
export const smartContracts = { readOnly };
export type * as SmartContracts from "./smart-contracts/index.js";

import { members } from "./stacking-pool/index.js";
export const stackingPool = { members };
import { stackingPool } from "./stacking-pool/index.js";
export type * as StackingPool from "./stacking-pool/index.js";

import { addressTransactions, getTransaction } from "./transactions/index.js";
export const transactions = { addressTransactions, getTransaction };
import { transactions } from "./transactions/index.js";
export type * as Transactions from "./transactions/index.js";

export const stacksApi = {
accounts,
blocks,
faucets,
info,
proofOfTransfer,
stackingPool,
transactions,
};
9 changes: 7 additions & 2 deletions src/stacks-api/info/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
export { coreApi } from "./core-api.js";
import { coreApi } from "./core-api.js";
export type * as CoreApi from "./core-api.js";

export { poxDetails } from "./pox-details.js";
import { poxDetails } from "./pox-details.js";
export type * as PoxDetails from "./pox-details.js";

export const info = {
coreApi,
poxDetails,
};
18 changes: 13 additions & 5 deletions src/stacks-api/proof-of-transfer/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
export { cycle } from "./cycle.js";
import { cycle } from "./cycle.js";
export type * as Cycle from "./cycle.js";

export { cycles } from "./cycles.js";
import { cycles } from "./cycles.js";
export type * as Cycles from "./cycles.js";

export { signerInCycle } from "./signer-in-cycle.js";
import { signerInCycle } from "./signer-in-cycle.js";
export type * as SignerInCycle from "./signer-in-cycle.js";

export { signersInCycle } from "./signers-in-cycle.js";
import { signersInCycle } from "./signers-in-cycle.js";
export type * as SignersInCycle from "./signers-in-cycle.js";

export { stackersForSignerInCycle } from "./stackers-for-signer-in-cycle.js";
import { stackersForSignerInCycle } from "./stackers-for-signer-in-cycle.js";
export type * as StackersForSignerInCycle from "./stackers-for-signer-in-cycle.js";

export const proofOfTransfer = {
cycle,
cycles,
signerInCycle,
signersInCycle,
stackersForSignerInCycle,
};
2 changes: 0 additions & 2 deletions src/stacks-api/smart-contracts/index.ts

This file was deleted.

6 changes: 5 additions & 1 deletion src/stacks-api/stacking-pool/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
export { members } from "./members.js";
import { members } from "./members.js";
export type * as Members from "./members.js";

export const stackingPool = {
members,
};
30 changes: 13 additions & 17 deletions src/stacks-api/stacking-pool/members.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { error, safePromise, success, type Result } from "../../utils/safe.js";
import { type ApiRequestOptions } from "../types.js";
import { type ApiPaginationOptions, type ApiRequestOptions } from "../types.js";
import * as v from "valibot";

export type Options = {
export type Args = {
poolPrincipal: string;
afterBlock?: number;
unanchored?: boolean;
limit?: number;
offset?: number;
};
} & ApiRequestOptions &
ApiPaginationOptions;

export const memberSchema = v.object({
stacker: v.string(),
Expand All @@ -28,27 +29,22 @@ export const membersResponseSchema = v.object({
});
export type MembersResponse = v.InferOutput<typeof membersResponseSchema>;

export async function members(
opts: Options,
apiOpts: ApiRequestOptions,
): Promise<Result<MembersResponse>> {
export async function members(args: Args): Promise<Result<MembersResponse>> {
const search = new URLSearchParams();
if (opts.afterBlock) search.append("after_block", opts.afterBlock.toString());
if (opts.unanchored) search.append("unanchored", "true");
if (opts.limit) search.append("limit", opts.limit.toString());
if (opts.offset) search.append("offset", opts.offset.toString());
if (args.afterBlock) search.append("after_block", args.afterBlock.toString());
if (args.unanchored) search.append("unanchored", "true");
if (args.limit) search.append("limit", args.limit.toString());
if (args.offset) search.append("offset", args.offset.toString());

const init: RequestInit = {};
if (apiOpts.apiKeyConfig) {
if (args.apiKeyConfig) {
init.headers = {
[apiOpts.apiKeyConfig.header]: apiOpts.apiKeyConfig.key,
[args.apiKeyConfig.header]: args.apiKeyConfig.key,
};
}

const res = await fetch(
`${apiOpts.baseUrl}/extended/beta/stacking/${opts.poolPrincipal}/delegations?${search}`,
init,
);
const endpoint = `${args.baseUrl}/extended/v1/pox4/${args.poolPrincipal}/delegations?${search}`;
const res = await fetch(endpoint, init);

if (!res.ok) {
return error({
Expand Down
9 changes: 7 additions & 2 deletions src/stacks-api/transactions/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
export { addressTransactions } from "./address-transactions.js";
import { addressTransactions } from "./address-transactions.js";
export type * as AddressTransactions from "./address-transactions.js";

export { getTransaction } from "./get-transaction.js";
import { getTransaction } from "./get-transaction.js";
export type * as GetTransaction from "./get-transaction.js";

export type * as Common from "./schemas.js";

export const transactions = {
addressTransactions,
getTransaction,
};
8 changes: 8 additions & 0 deletions src/stacks-api/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ export type ApiRequestOptions = {
apiKeyConfig?: ApiKeyConfig;
};

export type ProofAndTip = {
/**
* Returns object without the proof field when set to 0.
*/
proof?: number;
tip?: "latest" | string;
};

export type ApiPaginationOptions = {
/**
* The number of items to return. Each endpoint has its own maximum allowed
Expand Down
88 changes: 88 additions & 0 deletions src/stacks-rpc-api/fees/estimate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import * as v from "valibot";
import type { ApiRequestOptions } from "../../stacks-api/types.js";
import { error, safePromise, success, type Result } from "../../utils/safe.js";

export type Args = {
/**
* A hex-encoded serialization of the TransactionPayload for the transaction.
*/
transactionPayload: string;

/**
* An estimation of the final length (in bytes) of the transaction, including
* any post-conditions and signatures
*/
estimatedLength?: number;
} & ApiRequestOptions;

export const responseSchema = v.object({
estimated_cost_scalar: v.number(),
cost_scalar_change_by_byte: v.optional(v.number()),
estimated_cost: v.object({
read_count: v.number(),
read_length: v.number(),
runtime: v.number(),
write_count: v.number(),
write_length: v.number(),
}),
estimations: v.optional(
v.array(
v.object({
fee_rate: v.optional(v.number()),
fee: v.optional(v.number()),
}),
),
),
});
export type Response = v.InferOutput<typeof responseSchema>;

export async function estimate(args: Args): Promise<Result<Response>> {
//
const init: RequestInit = {};
if (args.apiKeyConfig) {
init.headers = {
[args.apiKeyConfig.header]: args.apiKeyConfig.key,
};
}
init.method = "POST";
init.body = JSON.stringify({
transaction_payload: args.transactionPayload,
...(args.estimatedLength ? { estimated_len: args.estimatedLength } : {}),
});
init.headers = { ...init.headers, "Content-Type": "application/json" };

const endpoint = `${args.baseUrl}/v2/fees/transaction`;
const res = await fetch(endpoint, init);
if (!res.ok) {
return error({
name: "FetchEstimateError",
message: "Failed to fetch estimate.",
data: {
status: res.status,
statusText: res.statusText,
endpoint,
bodyParseResult: await safePromise(res.text()),
},
});
}

const [jsonError, data] = await safePromise(res.json());
if (jsonError) {
return error({
name: "ParseBodyError",
message: "Failed to parse response body as JSON.",
data: jsonError,
});
}

const validationResult = v.safeParse(responseSchema, data);
if (!validationResult.success) {
return error({
name: "ValidateDataError",
message: "Failed to validate response data.",
data: validationResult,
});
}

return success(validationResult.output);
}
6 changes: 6 additions & 0 deletions src/stacks-rpc-api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { smartContracts } from "./smart-contracts/index.js";
export type * as SmartContracts from "./smart-contracts/index.js";

export const stacksRpcApi = {
smartContracts,
};
Loading