Skip to content

Commit

Permalink
Add message signing example
Browse files Browse the repository at this point in the history
  • Loading branch information
r-n-o committed Feb 22, 2024
1 parent 79ee67b commit f9b341f
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 0 deletions.
1 change: 1 addition & 0 deletions .ruby-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.0
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ See the [examples](./examples/) folder if you're looking for a complete sample p
## Examples

* [Whoami](./examples/whoami/): example showcasing API request signing in its simplest form
* [Signing](./examples/whoami/): example showcasing wallet creation and ETH message signing

## Using Turnkey in your Rails projects

Expand Down
6 changes: 6 additions & 0 deletions examples/signing/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# If you do not have an organization, create one at https://app.turnkey.com/dashboard/auth/initial
TURNKEY_ORGANIZATION_ID=<your-organization-id>
# API credentials. They need to be attached to a user in your organization.
# These credentials must be a valid hex-encoded public/private key pair (P256)
TURNKEY_API_PUBLIC_KEY=<your-public-key>
TURNKEY_API_PRIVATE_KEY=<your-private-key>
4 changes: 4 additions & 0 deletions examples/signing/Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
source 'https://rubygems.org'

gem 'dotenv'
gem 'turnkey_client', path: '../../turnkey_client/'
29 changes: 29 additions & 0 deletions examples/signing/Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
PATH
remote: ../../turnkey_client
specs:
turnkey_client (0.0.1)
json (~> 2.1, >= 2.1.0)
openssl (~> 3.2, >= 3.0.0)
typhoeus (~> 1.0, >= 1.0.1)

GEM
remote: https://rubygems.org/
specs:
dotenv (3.0.2)
ethon (0.16.0)
ffi (>= 1.15.0)
ffi (1.16.3)
json (2.7.1)
openssl (3.2.0)
typhoeus (1.4.1)
ethon (>= 0.9.0)

PLATFORMS
arm64-darwin-23

DEPENDENCIES
dotenv
turnkey_client!

BUNDLED WITH
2.2.3
22 changes: 22 additions & 0 deletions examples/signing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Who am I?

This examples shows how to use `turnkey_client` to create a new wallet and sign a message with it.

To run this example:
* `cp .env.example .env`
* Follow the instructions in the `.env` file to fill in values for `TURNKEY_ORGANIZATION_ID`, `TURNKEY_API_PUBLIC_KEY`, and `TURNKEY_API_PRIVATE_KEY`
* Install the dependencies: `bundle install`
* Then run the `signing.rb` script: `bundle exec ruby signing.rb`

You should be able to verify the signature produced via Etherscan. Here's an example run:

```
created new wallet successfully
successful signature
- address: 0xf0635c94F7bEEcF9abC77F512Bf33BB66Fe9997f
- message: "hello from Turnkey, in Ruby!"
- signature hash: 0x9b55914814658b4cb592ed6782f2e639b28b89d122240c34f7ea5d7afd48c5861271b008ae62d15131cdd95fbc6a8498ea8379e20ad8fa0956dfd207c6def1d21b
You can verify for yourself at https://etherscan.io/verifiedSignatures > "Verify Signature"
```

Proof of validity: https://etherscan.io/verifySig/36331
85 changes: 85 additions & 0 deletions examples/signing/signing.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
require 'turnkey_client'
require 'dotenv'
require 'json'
require 'date'

# Load local .env file
Dotenv.load

raise 'Please set TURNKEY_ORGANIZATION_ID in your .env file' if ENV['TURNKEY_ORGANIZATION_ID'].nil?

# Make a whoami request
begin
client = TurnkeyClient.configure do |c|
c.api_public_key = ENV['TURNKEY_API_PUBLIC_KEY']
c.api_private_key = ENV['TURNKEY_API_PRIVATE_KEY']
end

# https://docs.turnkey.com/api#tag/Wallets/operation/CreateWallet
now_in_ms = DateTime.now.strftime('%Q')

# We can also use `TurnkeyClient::V1CreateWalletRequest` to create the request object here
create_wallet_response = TurnkeyClient::WalletsApi.new(client).create_wallet(
{
type: 'ACTIVITY_TYPE_CREATE_WALLET',
organizationId: ENV['TURNKEY_ORGANIZATION_ID'],
timestampMs: DateTime.now.strftime('%Q'),
parameters: {
walletName: "Wallet @#{now_in_ms}",
mnemonicLength: 12,
accounts: [
{
curve: 'CURVE_SECP256K1',
pathFormat: 'PATH_FORMAT_BIP32',
# Default ETH account
path: "m/44'/60'/0'/0/0",
addressFormat: 'ADDRESS_FORMAT_ETHEREUM'
}
]
}
}
)

created_wallet = create_wallet_response&.activity&.dig(:result, :createWalletResult)
raise "Something went wrong: no wallet in activity response: #{create_wallet_response.to_hash}" if created_wallet.nil?

puts 'created new wallet successfully'

eth_address = created_wallet[:addresses].first

# Now sign!
# https://docs.turnkey.com/api#tag/Signing/operation/SignRawPayload
message = 'hello from Turnkey, in Ruby!'
eth_message = "\u0019Ethereum Signed Message:\n#{message.size}#{message}"

signature_response = TurnkeyClient::SigningApi.new(client).sign_raw_payload(
{
type: 'ACTIVITY_TYPE_SIGN_RAW_PAYLOAD_V2',
organizationId: ENV['TURNKEY_ORGANIZATION_ID'],
timestampMs: DateTime.now.strftime('%Q'),
parameters: {
signWith: eth_address,
payload: eth_message,
encoding: 'PAYLOAD_ENCODING_TEXT_UTF8',
hashFunction: 'HASH_FUNCTION_KECCAK256'
}
}
)

signature = signature_response&.activity&.dig(:result, :signRawPayloadResult)
raise "Something went wrong: no signature in activity response: #{signature_response.to_hash}" if signature.nil?

puts 'successful signature'

eth_v = if signature[:v] == '00'
'1b' # 27 in hex
else
'1c' # 28 in hex
end
puts "- address: #{eth_address}"
puts "- message: \"#{message}\""
puts "- signature hash: 0x#{signature[:r]}#{signature[:s]}#{eth_v}"
puts 'You can verify for yourself at https://etherscan.io/verifiedSignatures > "Verify Signature"'
rescue TurnkeyClient::ApiError => e
puts "Exception when calling Whoami endpoint: #{e}"
end

0 comments on commit f9b341f

Please sign in to comment.