Skip to content

Commit

Permalink
Merge pull-request #119
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewkmin committed Sep 19, 2023
2 parents 3f878f6 + 392c701 commit 4069b54
Show file tree
Hide file tree
Showing 21 changed files with 1,712 additions and 79 deletions.
3 changes: 3 additions & 0 deletions .github/actions/js-setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,6 @@ runs:
- name: Install dependencies
run: pnpm install -r --frozen-lockfile
shell: bash

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@cb603ca0abb544f301eaed59ac0baf579aa6aecf
10 changes: 9 additions & 1 deletion .github/workflows/js-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,15 @@ jobs:
run: pnpm run typecheck-all

- name: Test
run: pnpm run test-all
run: anvil & pnpm run test-all
env:
API_PUBLIC_KEY: ${{ secrets.API_PUBLIC_KEY }}
API_PRIVATE_KEY: ${{ secrets.API_PRIVATE_KEY }}
BASE_URL: "https://api.turnkey.com"
ORGANIZATION_ID: ${{ secrets.ORGANIZATION_ID }}
PRIVATE_KEY_ID: ${{ secrets.PRIVATE_KEY_ID }}
EXPECTED_ETH_ADDRESS: ${{ secrets.EXPECTED_ETH_ADDRESS }}
BANNED_TO_ADDRESS: "0x6F72eDB2429820c2A0606a9FC3cA364f5E9b2375"

- name: Prettier
run: pnpm run prettier-all:check
Expand Down
1 change: 1 addition & 0 deletions examples/with-ethers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"private": true,
"scripts": {
"start": "pnpm -w run build-all && tsx src/index.ts",
"start-advanced": "pnpm -w run build-all && tsx src/advanced.ts",
"start-legacy-sepolia": "pnpm -w run build-all && tsx src/legacySepolia.ts",
"clean": "rimraf ./dist ./.cache",
"typecheck": "tsc --noEmit"
Expand Down
115 changes: 115 additions & 0 deletions examples/with-ethers/src/advanced.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import * as path from "path";
import * as dotenv from "dotenv";

// Load environment variables from `.env.local`
dotenv.config({ path: path.resolve(process.cwd(), ".env.local") });

import { TurnkeySigner } from "@turnkey/ethers";
import { ethers } from "ethers";
import { TurnkeyClient } from "@turnkey/http";
import { ApiKeyStamper } from "@turnkey/api-key-stamper";
import { createNewEthereumPrivateKey } from "./createNewEthereumPrivateKey";

async function main() {
if (!process.env.PRIVATE_KEY_ID) {
// If you don't specify a `PRIVATE_KEY_ID`, we'll create one for you via calling the Turnkey API.
await createNewEthereumPrivateKey();
return;
}

const turnkeyClient = new TurnkeyClient(
{
baseUrl: process.env.BASE_URL!,
},
new ApiKeyStamper({
apiPublicKey: process.env.API_PUBLIC_KEY!,
apiPrivateKey: process.env.API_PRIVATE_KEY!,
})
);

// Initialize a Turnkey Signer
const turnkeySigner = new TurnkeySigner({
client: turnkeyClient,
organizationId: process.env.ORGANIZATION_ID!,
privateKeyId: process.env.PRIVATE_KEY_ID!,
});

// Bring your own provider (such as Alchemy or Infura: https://docs.ethers.org/v5/api/providers/)
const network = "goerli";
const provider = new ethers.providers.InfuraProvider(network);
const connectedSigner = turnkeySigner.connect(provider);
const address = await connectedSigner.getAddress();

print("Address:", address);

const baseMessage = "Hello Turnkey";

// 1. Sign a raw hex message
const hexMessage = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(baseMessage)
);
let signature = await connectedSigner.signMessage(hexMessage);
let recoveredAddress = ethers.utils.verifyMessage(hexMessage, signature);

print("Turnkey-powered signature - raw hex message:", `${signature}`);
assertEqual(recoveredAddress, address);

// 2. Sign a raw bytes message
const bytesMessage = ethers.utils.toUtf8Bytes(baseMessage);
signature = await connectedSigner.signMessage(bytesMessage);
recoveredAddress = ethers.utils.verifyMessage(bytesMessage, signature);

print("Turnkey-powered signature - raw bytes message:", `${signature}`);
assertEqual(recoveredAddress, address);

// 3. Sign typed data (EIP-712)
const typedData = {
types: {
// Note that we do not need to include `EIP712Domain` as a type here, as Ethers will automatically inject it for us
Person: [
{ name: "name", type: "string" },
{ name: "wallet", type: "address" },
],
},
domain: {
name: "EIP712 Test",
version: "1",
},
primaryType: "Person",
message: {
name: "Alice",
wallet: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
},
};

signature = await connectedSigner.signTypedData(
typedData.domain,
typedData.types,
typedData.message
);

recoveredAddress = ethers.utils.verifyTypedData(
typedData.domain,
typedData.types,
typedData.message,
signature
);

print("Turnkey-powered signature - typed data (EIP-712):", `${signature}`);
assertEqual(recoveredAddress, address);
}

main().catch((error) => {
console.error(error);
process.exit(1);
});

function print(header: string, body: string): void {
console.log(`${header}\n\t${body}\n`);
}

function assertEqual<T>(left: T, right: T) {
if (left !== right) {
throw new Error(`${JSON.stringify(left)} !== ${JSON.stringify(right)}`);
}
}
11 changes: 1 addition & 10 deletions examples/with-ethers/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ethers } from "ethers";
import { TurnkeyClient } from "@turnkey/http";
import { ApiKeyStamper } from "@turnkey/api-key-stamper";
import { createNewEthereumPrivateKey } from "./createNewEthereumPrivateKey";
import { print, assertEqual } from "./util";
import WETH_TOKEN_ABI from "./weth-contract-abi.json";

const WETH_TOKEN_ADDRESS_GOERLI = "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6";
Expand Down Expand Up @@ -123,13 +124,3 @@ main().catch((error) => {
console.error(error);
process.exit(1);
});

function print(header: string, body: string): void {
console.log(`${header}\n\t${body}\n`);
}

function assertEqual<T>(left: T, right: T) {
if (left !== right) {
throw new Error(`${JSON.stringify(left)} !== ${JSON.stringify(right)}`);
}
}
9 changes: 9 additions & 0 deletions examples/with-ethers/src/util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function print(header: string, body: string): void {
console.log(`${header}\n\t${body}\n`);
}

export function assertEqual<T>(left: T, right: T) {
if (left !== right) {
throw new Error(`${JSON.stringify(left)} !== ${JSON.stringify(right)}`);
}
}
2 changes: 1 addition & 1 deletion examples/with-viem-and-passkeys/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@
"react-dom": "18.2.0",
"react-hook-form": "^7.45.1",
"typescript": "5.1.3",
"viem": "^1.5.3"
"viem": "^1.10.0"
}
}
2 changes: 1 addition & 1 deletion examples/with-viem/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,6 @@
"dotenv": "^16.0.3",
"fetch": "^1.1.0",
"typescript": "5.1",
"viem": "^1.5.3"
"viem": "^1.10.0"
}
}
4 changes: 3 additions & 1 deletion examples/with-viem/src/advanced.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ async function main() {
});

const address = client.account.address;
print("Address:", address);

const baseMessage = "Hello Turnkey";

// 1. Sign a raw hex message
Expand Down Expand Up @@ -118,7 +120,7 @@ async function main() {
signature,
});

print("Turnkey-powered signature - typed data:", `${signature}`);
print("Turnkey-powered signature - typed data (EIP-712):", `${signature}`);
assertEqual(address, recoveredAddress);
}

Expand Down
8 changes: 8 additions & 0 deletions packages/ethers/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# If you want to run unit tests, populate these values and save this file as a new `.env` file
API_PUBLIC_KEY="<Turnkey API Public Key (that starts with 02 or 03)>"
API_PRIVATE_KEY="<Turnkey API Private Key>"
BASE_URL="https://api.turnkey.com"
ORGANIZATION_ID="<Turnkey organization ID>"
PRIVATE_KEY_ID="<Turnkey (crypto) private key ID>"
EXPECTED_ETH_ADDRESS="<Corresponding to the private key above>"
BANNED_TO_ADDRESS="<0x...>"
4 changes: 4 additions & 0 deletions packages/ethers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ main().catch((error) => {
});
```

## Testing (Local)

See `.env.example` to get your local testing environment right. Run `pnpm jest` to run the tests.

## More examples

| Example | Description |
Expand Down
4 changes: 2 additions & 2 deletions packages/ethers/src/__tests__/index-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { ApiKeyStamper } from "@turnkey/api-key-stamper";
// @ts-expect-error
const testCase: typeof test = (...argList) => {
if (!process.env.BANNED_TO_ADDRESS) {
// For now, this test requires certain environment variables to be injected (from Turnkey's internal environment)
// For now, this test requires certain environment variables to be injected (from Turnkey's internal environment, or a local `.env` file)
return test.skip(...argList);
}

Expand All @@ -28,7 +28,7 @@ describe("TurnkeySigner", () => {

beforeEach(async () => {
if (!process.env.BANNED_TO_ADDRESS) {
// For now, this test requires certain environment variables to be injected (from Turnkey's internal environment)
// For now, this test requires certain environment variables to be injected (from Turnkey's internal environment, or a local `.env` file)
return;
}

Expand Down
4 changes: 3 additions & 1 deletion packages/viem/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ API_PUBLIC_KEY="<Turnkey API Public Key (that starts with 02 or 03)>"
API_PRIVATE_KEY="<Turnkey API Private Key>"
BASE_URL="https://api.turnkey.com"
ORGANIZATION_ID="<Turnkey organization ID>"
PRIVATE_KEY_ID="<Turnkey (crypto) private key ID>"
PRIVATE_KEY_ID="<Turnkey (crypto) private key ID>"
EXPECTED_ETH_ADDRESS="<Corresponding to the private key above>"
BANNED_TO_ADDRESS="<0x...>"
1 change: 1 addition & 0 deletions packages/viem/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
src/__tests__/contracts/artifacts
4 changes: 4 additions & 0 deletions packages/viem/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ main().catch((error) => {
});
```

## Testing (Local)

See `.env.example` to get your local testing environment right. In order to run the tests, run an Anvil node in one shell (via `pnpm anvil`), and run `pnpm jest` in another.

## See also

- [`@turnkey/example-with-viem`](https://github.com/tkhq/sdk/tree/main/examples/with-viem): example using this package to create, sign, and broadcast a transaction on Sepolia (Ethereum testnet)
Expand Down
14 changes: 14 additions & 0 deletions packages/viem/hardhat.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// require("@nomiclabs/hardhat-ethers");
// require("hardhat-jest-plugin");

/** @type import('hardhat/config').HardhatUserConfig */
const config = {
solidity: "0.8.17",
paths: {
sources: "./src/__tests__/contracts/source",
artifacts: "./src/__tests__/contracts/artifacts",
cache: "./.cache",
},
};

module.exports = config;
11 changes: 7 additions & 4 deletions packages/viem/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,23 @@
"build": "tsc",
"clean": "rimraf ./dist ./.cache",
"test": "jest",
"typecheck": "tsc -p tsconfig.typecheck.json"
"anvil": "anvil",
"typecheck": "tsc -p tsconfig.typecheck.json",
"compile:contracts": "hardhat compile"
},
"peerDependencies": {
"viem": "^1.5.0"
"viem": "^1.10.0"
},
"dependencies": {
"@turnkey/http": "workspace:*",
"@turnkey/api-key-stamper": "workspace:*",
"@turnkey/http": "workspace:*",
"cross-fetch": "^4.0.0",
"typescript": "5.1"
},
"devDependencies": {
"@types/jest": "^29.5.3",
"jest": "^29.3.1",
"viem": "^1.5.3"
"viem": "^1.10.0"
},
"engines": {
"node": ">=18.0.0"
Expand Down
Loading

0 comments on commit 4069b54

Please sign in to comment.