Skip to content

Commit

Permalink
Create node example (#1339)
Browse files Browse the repository at this point in the history
  • Loading branch information
tarrencev authored Jan 29, 2025
1 parent ae7b522 commit d46d8e3
Show file tree
Hide file tree
Showing 19 changed files with 1,451 additions and 172 deletions.
1 change: 1 addition & 0 deletions examples/node/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.cartridge
33 changes: 33 additions & 0 deletions examples/node/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Cartridge Node.js Session Example

This example demonstrates how to use the Cartridge session controller with Node.js

## Setup

1. Install dependencies:

```bash
npm install
```

2. Run the example:

```bash
npm start
```

## What's happening?

The example demonstrates:
1. Setting up a filesystem backend for session storage
2. Creating a session controller instance
3. Creating a new session with specific policies
4. Executing a transaction using the session

## Customization

To use this example with your own contract:

1. Replace the contract address (`0x123...`) with your actual contract address
2. Modify the policies to match your contract's methods
3. Update the transaction parameters in the `execute` call to match your use case
21 changes: 21 additions & 0 deletions examples/node/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "cartridge-node-example",
"version": "1.0.0",
"description": "Example of using Cartridge session controller with Node.js",
"type": "module",
"scripts": {
"build": "tsc",
"start": "node --experimental-wasm-modules dist/session.js",
"dev": "node --experimental-wasm-modules --import tsx src/session.ts"
},
"dependencies": {
"@cartridge/account-wasm": "workspace:*",
"@cartridge/controller": "workspace:*",
"starknet": "catalog:"
},
"devDependencies": {
"typescript": "^5.3.3",
"tsx": "^4.7.0",
"@types/node": "^22.12.0"
}
}
74 changes: 74 additions & 0 deletions examples/node/src/session.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import SessionProvider, {
ControllerError,
} from "@cartridge/controller/session/node";
import { constants } from "starknet";
import path from "path";

export const STRK_CONTRACT_ADDRESS =
"0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7";

async function main() {
// Path to store session
const storagePath =
process.env.CARTRIDGE_STORAGE_PATH ||
path.join(process.cwd(), ".cartridge");

// Create a session provider
const provider = new SessionProvider({
rpc: "https://api.cartridge.gg/x/starknet/sepolia",
chainId: constants.StarknetChainId.SN_SEPOLIA,
policies: {
contracts: {
[STRK_CONTRACT_ADDRESS]: {
methods: [
{
name: "approve",
entrypoint: "approve",
description: "Approve spending of tokens",
},
{ name: "transfer", entrypoint: "transfer" },
],
},
},
},
basePath: storagePath,
});
try {
// Connect and create session
const account = await provider.connect();
console.log("Session initialized!");

if (account) {
console.log("Account address:", account.address);

// Example: Transfer ETH
const amount = "0x0";
const recipient = account.address; // Replace with actual recipient address

const result = await account.execute([
{
contractAddress: STRK_CONTRACT_ADDRESS,
entrypoint: "transfer",
calldata: [recipient, amount, "0x0"],
},
]);

console.log("Transaction hash:", result.transaction_hash);
} else {
console.log("Please complete the session creation in your browser");
}
} catch (error: unknown) {
const controllerError = error as ControllerError;
if (controllerError.code) {
console.error("Session error:", {
code: controllerError.code,
message: controllerError.message,
data: controllerError.data,
});
} else {
console.error("Session error:", error);
}
}
}

main().catch(console.error);
16 changes: 16 additions & 0 deletions examples/node/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"esModuleInterop": true,
"strict": true,
"skipLibCheck": true,
"outDir": "./dist",
"rootDir": "./src",
"declaration": true,
"allowJs": true,
"resolveJsonModule": true
},
"include": ["src/**/*"]
}
8 changes: 0 additions & 8 deletions packages/account-wasm/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,3 @@ pnpm wasm-pack build --target bundler --out-dir ./pkg-controller --release --fea

# Build session bundle
pnpm wasm-pack build --target bundler --out-dir ./pkg-session --release --features "console-error-panic,session_account"

# Workaround for ESM `import` error in NextJS.
# This removes `"type": "module"` field from the package.json files
for dir in pkg-controller pkg-session; do
mv $dir/package.json $dir/temp.json
jq -r 'del(.type)' $dir/temp.json >$dir/package.json
rm $dir/temp.json
done
43 changes: 14 additions & 29 deletions packages/account-wasm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,40 @@
"name": "@cartridge/account-wasm",
"version": "0.6.0",
"description": "Wasm bindings for Cartridge Controller and Session Account",
"main": "./pkg-controller/account_wasm.js",
"type": "module",
"main": "./pkg-controller/account_wasm.js",
"module": "./pkg-controller/account_wasm.js",
"types": "./pkg-controller/account_wasm.d.ts",
"scripts": {
"build:deps": "./build.sh"
},
"files": [
"./pkg-controller/account_wasm_bg.wasm",
"./pkg-controller/account_wasm.js",
"./pkg-controller/account_wasm_bg.js",
"./pkg-controller/account_wasm.d.ts",
"./pkg-session/account_wasm_bg.wasm",
"./pkg-session/account_wasm.js",
"./pkg-session/account_wasm_bg.js",
"./pkg-session/account_wasm.d.ts"
"pkg-controller",
"pkg-session"
],
"exports": {
".": {
"types": "./pkg-controller/account_wasm.d.ts",
"default": "./pkg-controller/account_wasm.js"
"import": "./pkg-controller/account_wasm.js",
"require": "./pkg-controller/account_wasm.js"
},
"./controller": {
"types": "./pkg-controller/account_wasm.d.ts",
"default": "./pkg-controller/account_wasm.js"
"import": "./pkg-controller/account_wasm.js",
"require": "./pkg-controller/account_wasm.js"
},
"./session": {
"types": "./pkg-session/account_wasm.d.ts",
"default": "./pkg-session/account_wasm.js"
"import": "./pkg-session/account_wasm.js",
"require": "./pkg-session/account_wasm.js"
}
},
"sideEffects": [
"**/*.wasm",
"./pkg-controller/account_wasm.js",
"./pkg-session/account_wasm.js",
"./pkg-controller/snippets/*",
"./pkg-session/snippets/*"
"./pkg-session/account_wasm.js"
],
"typesVersions": {
"*": {
"controller": [
"./pkg-controller/account_wasm.d.ts"
],
"session": [
"./pkg-session/account_wasm.d.ts"
]
}
},
"devDependencies": {
"@cartridge/tsconfig": "workspace:*",
"tsup": "catalog:",
"typescript": "catalog:",
"wasm-pack": "^0.13.0"
}
}
}
30 changes: 30 additions & 0 deletions packages/account-wasm/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,36 @@ impl From<FromStrError> for JsControllerError {
}
}

impl From<account_sdk::signers::SignError> for JsControllerError {
fn from(error: account_sdk::signers::SignError) -> Self {
JsControllerError {
code: ErrorCode::SignError,
message: error.to_string(),
data: None,
}
}
}

impl From<url::ParseError> for JsControllerError {
fn from(error: url::ParseError) -> Self {
JsControllerError {
code: ErrorCode::UrlParseError,
message: error.to_string(),
data: None,
}
}
}

impl From<starknet::accounts::NotPreparedError> for JsControllerError {
fn from(error: starknet::accounts::NotPreparedError) -> Self {
JsControllerError {
code: ErrorCode::StarknetUnexpectedError,
message: error.to_string(),
data: None,
}
}
}

impl fmt::Display for JsControllerError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let json = serde_json::json!({
Expand Down
Loading

0 comments on commit d46d8e3

Please sign in to comment.