Skip to content
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
1,459 changes: 1,459 additions & 0 deletions sdk/package-lock.json

Large diffs are not rendered by default.

79 changes: 79 additions & 0 deletions sdk/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"name": "@runelabsxyz/guilds-sdk",
"version": "0.1.0",
"description": "Typed TypeScript SDK for RuneLabs Guilds contracts",
"license": "MIT",
"type": "module",
"sideEffects": false,
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"files": [
"dist",
"README.md",
"CHANGELOG.md",
"scripts",
"generated"
],
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
},
"./core": {
"types": "./dist/core/index.d.ts",
"import": "./dist/core/index.js"
},
"./types": {
"types": "./dist/types/index.d.ts",
"import": "./dist/types/index.js"
},
"./utils": {
"types": "./dist/utils/index.d.ts",
"import": "./dist/utils/index.js"
},
"./errors": {
"types": "./dist/errors/index.d.ts",
"import": "./dist/errors/index.js"
},
"./client": {
"types": "./dist/client/index.d.ts",
"import": "./dist/client/index.js"
},
"./bindings": {
"types": "./dist/bindings/index.d.ts",
"import": "./dist/bindings/index.js"
},
"./config": {
"types": "./dist/config/index.d.ts",
"import": "./dist/config/index.js"
},
"./package.json": "./package.json"
},
"scripts": {
"clean": "rm -rf dist",
"build": "tsc -p tsconfig.build.json",
"typecheck": "tsc -p tsconfig.json --noEmit",
"typecheck:examples": "tsc -p tsconfig.examples.json --noEmit",
"test": "vitest run",
"test:watch": "vitest",
"sync:contracts": "node ./scripts/sync-contract-signature.mjs",
"check:compat": "node ./scripts/check-contract-compat.mjs",
"verify": "npm run typecheck && npm run typecheck:examples && npm run check:compat && npm run test && npm run build"
},
"keywords": [
"starknet",
"guilds",
"runelabs",
"sdk",
"typescript"
],
"engines": {
"node": ">=20"
},
"devDependencies": {
"@types/node": "^22.10.2",
"typescript": "^5.7.3",
"vitest": "^2.1.8"
}
}
71 changes: 71 additions & 0 deletions sdk/src/bindings/factory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import type { ContractTransport } from '../core/transport.js';
import type { CreateGuildParams, GuildAddresses, StarknetAddress } from '../types/contracts.js';

export interface FactoryBindings {
createGuild(factory: StarknetAddress, params: CreateGuildParams): Promise<{ transactionHash: string }>;
getGuild(factory: StarknetAddress, guildAddress: StarknetAddress): Promise<string[]>;
isNameTaken(factory: StarknetAddress, name: string): Promise<boolean>;
isTickerTaken(factory: StarknetAddress, ticker: string): Promise<boolean>;
}

function toBool(word: string): boolean {
return word !== '0x0' && word !== '0';
}

export function createFactoryBindings(transport: ContractTransport): FactoryBindings {
return {
async createGuild(factory, params): Promise<{ transactionHash: string }> {
const calldata = [
params.name,
params.ticker,
params.depositToken,
`0x${params.depositAmount.toString(16)}`,
`0x${params.initialTokenSupply.toString(16)}`,
`0x${params.governorConfig.votingDelay.toString(16)}`,
`0x${params.governorConfig.votingPeriod.toString(16)}`,
`0x${params.governorConfig.proposalThreshold.toString(16)}`,
`0x${params.governorConfig.quorumBps.toString(16)}`,
`0x${params.governorConfig.timelockDelay.toString(16)}`,
];
return transport.invoke({
contractAddress: factory,
entrypoint: 'create_guild',
calldata,
});
},

async getGuild(factory, guildAddress): Promise<string[]> {
return transport.call<string[]>({
contractAddress: factory,
entrypoint: 'get_guild',
calldata: [guildAddress],
});
},

async isNameTaken(factory, name): Promise<boolean> {
const raw = await transport.call<string[]>({
contractAddress: factory,
entrypoint: 'is_name_taken',
calldata: [name],
});
return toBool(raw[0] ?? '0x0');
},

async isTickerTaken(factory, ticker): Promise<boolean> {
const raw = await transport.call<string[]>({
contractAddress: factory,
entrypoint: 'is_ticker_taken',
calldata: [ticker],
});
return toBool(raw[0] ?? '0x0');
},
};
}

export function decodeGuildAddresses(raw: string[]): GuildAddresses {
return {
guild: raw[0] as StarknetAddress,
token: raw[1] as StarknetAddress,
governor: raw[2] as StarknetAddress,
};
}
111 changes: 111 additions & 0 deletions sdk/src/bindings/guild.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import type { ContractTransport } from '../core/transport.js';
import type {
GovernanceActionParams,
ShareActionParams,
StarknetAddress,
TreasuryActionParams,
VoteParams,
WireGuildAddressesParams,
} from '../types/contracts.js';

export interface GuildBindings {
setGovernorAddress(guild: StarknetAddress, governor: StarknetAddress): Promise<{ transactionHash: string }>;
executeCoreAction(params: TreasuryActionParams): Promise<{ transactionHash: string }>;
buyShares(params: ShareActionParams): Promise<{ transactionHash: string }>;
redeemShares(params: ShareActionParams): Promise<{ transactionHash: string }>;
getGovernorAddress(guild: StarknetAddress): Promise<StarknetAddress>;
getTokenAddress(guild: StarknetAddress): Promise<StarknetAddress>;
propose(params: GovernanceActionParams): Promise<{ transactionHash: string }>;
vote(params: VoteParams): Promise<{ transactionHash: string }>;
}

export function createGuildBindings(transport: ContractTransport): GuildBindings {
return {
async setGovernorAddress(guild, governor): Promise<{ transactionHash: string }> {
return transport.invoke({
contractAddress: guild,
entrypoint: 'set_governor_address',
calldata: [governor],
});
},

async executeCoreAction(params): Promise<{ transactionHash: string }> {
const calldata = [
`0x${params.actionType.toString(16)}`,
params.target,
params.token,
`0x${params.amount.toString(16)}`,
`0x${params.calldata.length.toString(16)}`,
...params.calldata,
];
return transport.invoke({
contractAddress: params.guild,
entrypoint: 'execute_core_action',
calldata,
});
},

async buyShares(params): Promise<{ transactionHash: string }> {
return transport.invoke({
contractAddress: params.guild,
entrypoint: 'buy_shares',
calldata: [`0x${params.amount.toString(16)}`],
});
},

async redeemShares(params): Promise<{ transactionHash: string }> {
return transport.invoke({
contractAddress: params.guild,
entrypoint: 'redeem_shares',
calldata: [`0x${params.amount.toString(16)}`],
});
},

async getGovernorAddress(guild): Promise<StarknetAddress> {
const raw = await transport.call<string[]>({
contractAddress: guild,
entrypoint: 'get_governor_address',
calldata: [],
});
return raw[0] as StarknetAddress;
},

async getTokenAddress(guild): Promise<StarknetAddress> {
const raw = await transport.call<string[]>({
contractAddress: guild,
entrypoint: 'get_token_address',
calldata: [],
});
return raw[0] as StarknetAddress;
},

async propose(params): Promise<{ transactionHash: string }> {
const calldata = [
`0x${params.targets.length.toString(16)}`,
...params.targets,
`0x${params.values.length.toString(16)}`,
...params.values.map((v) => `0x${v.toString(16)}`),
`0x${params.calldatas.length.toString(16)}`,
...params.calldatas,
params.description,
];
return transport.invoke({
contractAddress: params.governor,
entrypoint: 'propose',
calldata,
});
},

async vote(params): Promise<{ transactionHash: string }> {
return transport.invoke({
contractAddress: params.governor,
entrypoint: 'cast_vote',
calldata: [`0x${params.proposalId.toString(16)}`, `0x${params.support.toString(16)}`],
});
},
};
}

export function wireAddresses(input: WireGuildAddressesParams): WireGuildAddressesParams {
return input;
}
2 changes: 2 additions & 0 deletions sdk/src/bindings/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './factory.js';
export * from './guild.js';
7 changes: 7 additions & 0 deletions sdk/src/client/create-client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { ContractTransport } from '../core/transport.js';
import type { GuildsClientOptions } from '../types/network.js';
import { DefaultGuildsClient, type GuildsClient } from './guilds-client.js';

export function createGuildsClient(transport: ContractTransport, options: GuildsClientOptions): GuildsClient {
return new DefaultGuildsClient(transport, options);
}
Loading
Loading