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
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -135,3 +135,8 @@ turnkey.json

# turborepo
.turbo

# Foundry
out/
cache/
broadcast/
4 changes: 4 additions & 0 deletions examples/foundry/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
TURNKEY_API_PRIVATE_KEY="<Turnkey API Private Key>"
TURNKEY_ORGANIZATION_ID="<Turnkey organization ID>"
TURNKEY_ADDRESS="<Turnkey Wallet Account Address, Private Key Address, or Private Key ID>"
FOUNDRY_DISABLE_NIGHTLY_WARNING="true" # required until production release
88 changes: 88 additions & 0 deletions examples/foundry/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Example: `foundry`

This example shows how to set up and broadcast a smart contract from a Turnkey wallet using Foundry & Forge.

## Getting started

### 0 / Foundry versioning

Make sure you have [Foundry](https://getfoundry.sh/introduction/installation) installed locally.
Until >v1.4.4 release, it is also necessary to use a Nightly build for the Turnkey flag to be enabled.

```bash
$ curl -L https://foundry.paradigm.xyz | bash
$ foundryup --install nightly
```

### 1/ Cloning the example

```bash
$ git clone https://github.com/tkhq/sdk
$ cd sdk/examples/foundry/
```

### 2/ Setting up Turnkey

The first step is to set up your Turnkey organization and account. By following the [Quickstart](https://docs.turnkey.com/getting-started/quickstart) guide, you should have:

- A public/private API key pair for Turnkey
- An organization ID
- A Turnkey wallet account (address), private key address, or a private key ID

Once you've gathered these values, add them to a new `.env` file. Notice that your private key should be securely managed and **_never_** be committed to git.

```bash
$ cp .env.example .env
```

Now open `.env` and add the missing environment variables:

- `TURNKEY_API_PRIVATE_KEY`
- `TURNKEY_ORGANIZATION_ID`
- `TURNKEY_ADDRESS` -- a Turnkey wallet account address, private key address, or private key ID

For convenience we have hardcoded several popular chains and RPCs in `foundry.toml`, but you're welcome to change for different values.

### 3/ Running the sample deploy script

The following command will compile and broadcast Foundry's demo `Counter.sol` contract to the Sepolia network.
You will need some SepoliaETH in your Turnkey wallet address.

```bash
$ forge script script/Counter.s.sol --rpc-url sepolia --turnkey --broadcast
```

Visit the relevant chain explorer to view your transaction; you have successfully signed and deployed your first contract with Turnkey!

See the following for a sample output:

```
[⠊] Compiling...
No files changed, compilation skipped
Script ran successfully.

## Setting up 1 EVM.

==========================

Chain 11155111

Estimated gas price: 0.001037667 gwei

Estimated total gas used for script: 203856

Estimated amount required: 0.000000211534643952 ETH

==========================

##### sepolia
✅ [Success] Hash: 0xf492f7059d91ec1b91537a82b55289d1091e2a498db2881bd04d19b26ad29e0d
Contract Address: 0x2352D015613705F2c365dEead916d45BAaf547d4
Block: 9624270
Paid: 0.000000162718420767 ETH (156813 gas * 0.001037659 gwei)

✅ Sequence #1 on sepolia | Total Paid: 0.000000162718420767 ETH (156813 gas * avg 0.001037659 gwei)


==========================
```
8 changes: 8 additions & 0 deletions examples/foundry/foundry.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"lib/forge-std": {
"tag": {
"name": "v1.11.0",
"rev": "8e40513d678f392f398620b3ef2b418648b33e89"
}
}
}
16 changes: 16 additions & 0 deletions examples/foundry/foundry.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
[profile.default]
src = "src"
out = "out"
libs = ["lib"]

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options

[rpc_endpoints]
base = "https://mainnet.base.org"
baseSepolia = "https://sepolia.base.org"
ethereum = "https://ethereum.publicnode.com"
sepolia = "https://ethereum-sepolia-rpc.publicnode.com"
polygon = "https://polygon-rpc.com"
polygonAmoy = "https://rpc-amoy.polygon.technology"
monadTestnet = "https://testnet-rpc.monad.xyz/"
celo = "https://forno.celo.org"
1 change: 1 addition & 0 deletions examples/foundry/lib/forge-std/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
src/Vm.sol linguist-generated
1 change: 1 addition & 0 deletions examples/foundry/lib/forge-std/.github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* @danipopes @klkvr @mattsse @grandizzy @yash-atreya @zerosnacks @onbjerg @0xrusowsky
6 changes: 6 additions & 0 deletions examples/foundry/lib/forge-std/.github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
142 changes: 142 additions & 0 deletions examples/foundry/lib/forge-std/.github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
name: CI

permissions: {}

on:
workflow_dispatch:
pull_request:
push:
branches:
- master

jobs:
build:
name: build +${{ matrix.toolchain }} ${{ matrix.flags }}
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
strategy:
fail-fast: false
matrix:
toolchain: [stable, nightly]
flags:
- ""
- --via-ir
- --use solc:0.8.17 --via-ir
- --use solc:0.8.17
- --use solc:0.8.0
- --use solc:0.7.6
- --use solc:0.7.0
- --use solc:0.6.2
- --use solc:0.6.12
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- uses: foundry-rs/foundry-toolchain@v1
- run: forge --version
- run: |
case "${{ matrix.flags }}" in
*"solc:0.8.0"* | *"solc:0.7"* | *"solc:0.6"*)
forge build --skip test --skip Config --skip StdConfig --skip LibVariable --deny-warnings ${{ matrix.flags }}
;;
*)
forge build --skip test --deny-warnings ${{ matrix.flags }}
;;
esac
# via-ir compilation time checks.
- if: contains(matrix.flags, '--via-ir')
run: forge build --skip test --deny-warnings ${{ matrix.flags }} --contracts 'test/compilation/*'

test:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
strategy:
fail-fast: false
matrix:
toolchain: [stable, nightly]
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- uses: foundry-rs/foundry-toolchain@v1
with:
version: ${{ matrix.toolchain }}
- run: forge --version
- run: |
if [ "${{ matrix.toolchain }}" = "stable" ]; then
forge test -vvv --no-match-path "test/Config.t.sol"
else
forge test -vvv
fi

fmt:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- uses: foundry-rs/foundry-toolchain@v1
- run: forge --version
- run: forge fmt --check

typos:
runs-on: ubuntu-latest
timeout-minutes: 10
permissions:
contents: read
steps:
- uses: actions/checkout@v5
with:
persist-credentials: false
- uses: crate-ci/typos@7436548694def3314aacd93ed06c721b1f91ea04 # v1

codeql:
name: Analyze (${{ matrix.language }})
runs-on: ubuntu-latest
permissions:
security-events: write
actions: read
contents: read
strategy:
fail-fast: false
matrix:
include:
- language: actions
build-mode: none
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
build-mode: ${{ matrix.build-mode }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
with:
category: "/language:${{matrix.language}}"

ci-success:
runs-on: ubuntu-latest
if: always()
needs:
- build
- test
- fmt
- typos
- codeql
timeout-minutes: 10
steps:
- name: Decide whether the needed jobs succeeded or failed
uses: re-actors/alls-green@05ac9388f0aebcb5727afa17fcccfecd6f8ec5fe # release/v1
with:
jobs: ${{ toJSON(needs) }}
36 changes: 36 additions & 0 deletions examples/foundry/lib/forge-std/.github/workflows/sync.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Sync Release Branch

permissions: {}

on:
release:
types:
- created

jobs:
sync-release-branch:
runs-on: ubuntu-latest
permissions:
contents: write
if: startsWith(github.event.release.tag_name, 'v1')
steps:
- name: Check out the repo
uses: actions/checkout@v5
with:
persist-credentials: true
fetch-depth: 0
ref: v1

# The email is derived from the bots user id,
# found here: https://api.github.com/users/github-actions%5Bbot%5D
- name: Configure Git
run: |
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com

- name: Sync Release Branch
run: |
git fetch --tags
git checkout v1
git reset --hard ${GITHUB_REF}
git push --force
4 changes: 4 additions & 0 deletions examples/foundry/lib/forge-std/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
cache/
out/
.vscode
.idea
Loading
Loading