Class: Privy::Services::Wallets

Inherits:
Resources::Wallets show all
Defined in:
lib/privy/public_api/services/wallets.rb

Instance Attribute Summary collapse

Attributes inherited from Resources::Wallets

#balance, #swap, #transactions

Instance Method Summary collapse

Methods inherited from Resources::Wallets

#_init_import, #_submit_import, #_transfer, #authenticate_with_jwt, #create_wallets_with_recovery, #get, #get_wallet_by_address, #list

Constructor Details

#initialize(client:, privy_client:) ⇒ Wallets

Returns a new instance of Wallets.



11
12
13
14
15
# File 'lib/privy/public_api/services/wallets.rb', line 11

def initialize(client:, privy_client:)
  super(client: client)
  @privy_client = privy_client
  @earn = Privy::Services::Earn.new(client: client, privy_client: privy_client)
end

Instance Attribute Details

#earnPrivy::Services::Earn (readonly)



9
10
11
# File 'lib/privy/public_api/services/wallets.rb', line 9

def earn
  @earn
end

#privy_clientObject (readonly)

Returns the value of attribute privy_client.



6
7
8
# File 'lib/privy/public_api/services/wallets.rb', line 6

def privy_client
  @privy_client
end

Instance Method Details

#create(wallet_create_params:, idempotency_key: nil, request_options: nil) ⇒ Privy::Models::Wallet

Create a new wallet on the requested chain and for the requested owner.

Examples:

Create an ownerless Ethereum wallet

client.wallets.create(wallet_create_params: {chain_type: :ethereum})

Create a wallet with a P-256 key owner

client.wallets.create(wallet_create_params: {
  chain_type: :ethereum,
  owner: {public_key: base64_p256_public_key}
})

Parameters:

  • wallet_create_params (Hash)

    Body parameters for wallet creation.

  • idempotency_key (String, nil) (defaults to: nil)

    Ensures the request is executed only once.

  • request_options (Privy::RequestOptions, Hash, nil) (defaults to: nil)

    Transport-level config (timeouts, retries).

Options Hash (wallet_create_params:):

  • :chain_type (Symbol)

    The wallet chain type (required).

  • :owner (Hash, nil)

    Owner specified as user_id: or public_key:.

  • :owner_id (String, nil)

    Key quorum ID to set as owner.

  • :policy_ids (Array<String>, nil)

    Up to one policy ID to enforce.

  • :display_name (String, nil)

    A human-readable label for the wallet.

  • :external_id (String, nil)

    Customer-provided identifier for external mapping.

  • :additional_signers (Array<Hash>, nil)

    Additional signers for the wallet.

Returns:



40
41
42
43
44
# File 'lib/privy/public_api/services/wallets.rb', line 40

def create(wallet_create_params:, idempotency_key: nil, request_options: nil)
  combined_params = wallet_create_params.merge(request_options: request_options)
  combined_params[:privy_idempotency_key] = idempotency_key if idempotency_key
  super(combined_params)
end

#export(wallet_id, export_seed_phrase: nil, authorization_context: nil, request_expiry: nil, request_options: nil) ⇒ Hash

Export a wallet’s private key or seed phrase via HPKE.

Parameters:

  • wallet_id (String)

    ID of the wallet to export.

  • export_seed_phrase (Boolean, nil) (defaults to: nil)

    Whether to export the seed phrase instead of the private key.

  • authorization_context (Privy::Authorization::AuthorizationContext, nil) (defaults to: nil)

    Authorization context for owned wallets.

  • request_expiry (Integer, nil) (defaults to: nil)

    Absolute Unix-ms timestamp at which the request expires.

  • request_options (Privy::RequestOptions, Hash, nil) (defaults to: nil)

    Transport-level config (timeouts, retries).

Returns:

  • (Hash)

    String



312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
# File 'lib/privy/public_api/services/wallets.rb', line 312

def export(
  wallet_id,
  export_seed_phrase: nil,
  authorization_context: nil,
  request_expiry: nil,
  request_options: nil
)
  recipient = Privy::Cryptography::HpkeRecipient.new
  export_params = {
    encryption_type: "HPKE",
    recipient_public_key: Base64.strict_encode64(recipient.public_key_spki)
  }
  export_params[:export_seed_phrase] = export_seed_phrase unless export_seed_phrase.nil?

  prepared = Privy::Authorization.prepare_request(
    privy_client,
    method: :post,
    url: Privy::Authorization.signed_url(privy_client, "v1/wallets/#{wallet_id}/export"),
    body: export_params,
    authorization_context: authorization_context,
    request_expiry: privy_client.compute_request_expiry(request_expiry)
  )
  combined_params = export_params.merge(request_options: request_options)
  Privy::Authorization.merge_prepared_headers!(combined_params, prepared.headers)

  response = super(wallet_id, combined_params)
  unless response.encryption_type.to_s == "HPKE"
    raise Privy::Errors::Error, "Invalid encryption type: #{response.encryption_type}"
  end

  private_key = recipient.decrypt(
    Base64.strict_decode64(response.encapsulated_key),
    Base64.strict_decode64(response.ciphertext)
  )

  {private_key: private_key.force_encoding(Encoding::UTF_8)}
end

#export_private_key(wallet_id, authorization_context: nil, request_expiry: nil, request_options: nil) ⇒ Hash

Export a wallet’s private key via HPKE.

Returns:

  • (Hash)

    String



353
354
355
356
357
358
359
360
361
# File 'lib/privy/public_api/services/wallets.rb', line 353

def export_private_key(wallet_id, authorization_context: nil, request_expiry: nil, request_options: nil)
  export(
    wallet_id,
    export_seed_phrase: false,
    authorization_context: authorization_context,
    request_expiry: request_expiry,
    request_options: request_options
  )
end

#export_seed_phrase(wallet_id, authorization_context: nil, request_expiry: nil, request_options: nil) ⇒ Hash

Export a wallet’s seed phrase via HPKE.

Returns:

  • (Hash)

    String



366
367
368
369
370
371
372
373
374
375
# File 'lib/privy/public_api/services/wallets.rb', line 366

def export_seed_phrase(wallet_id, authorization_context: nil, request_expiry: nil, request_options: nil)
  exported = export(
    wallet_id,
    export_seed_phrase: true,
    authorization_context: authorization_context,
    request_expiry: request_expiry,
    request_options: request_options
  )
  {seed_phrase: exported.fetch(:private_key)}
end

#import(wallet:, additional_signers: nil, display_name: nil, external_id: nil, owner: nil, owner_id: nil, policy_ids: nil, request_options: nil) ⇒ Privy::Models::Wallet

Import an externally generated wallet by encrypting its entropy with HPKE.

Parameters:

  • wallet (Hash)

    Import wallet parameters plus :private_key entropy.

  • request_options (Privy::RequestOptions, Hash, nil) (defaults to: nil)

    Transport-level config (timeouts, retries).

Options Hash (wallet:):

  • :private_key (String)

    Private key or seed phrase entropy to import.

  • :entropy_type (String, Symbol)

    “hd” or “private-key”.

  • :chain_type (String, Symbol)

    “ethereum” or “solana”.

Returns:

Raises:



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/privy/public_api/services/wallets.rb', line 55

def import(
  wallet:,
  additional_signers: nil,
  display_name: nil,
  external_id: nil,
  owner: nil,
  owner_id: nil,
  policy_ids: nil,
  request_options: nil
)
  import_wallet = wallet.transform_keys { |key| key.respond_to?(:to_sym) ? key.to_sym : key }
  private_key = import_wallet.delete(:private_key)
  raise Privy::Errors::Error, "wallet.private_key is required" if private_key.nil?
  if import_wallet.key?(:hpke_config)
    raise Privy::Errors::Error,
          "wallet.hpke_config is not supported: encryption parameters are fixed by the SDK"
  end

  private_key_bytes = Privy::WalletEntropy.entropy_to_bytes(
    entropy: private_key,
    entropy_type: import_wallet.fetch(:entropy_type),
    chain_type: import_wallet.fetch(:chain_type)
  )

  init_response = _init_import(
    body: import_wallet.merge(encryption_type: "HPKE"),
    request_options: request_options
  )
  unless init_response.encryption_type.to_s == "HPKE"
    raise Privy::Errors::Error, "Invalid encryption type: #{init_response.encryption_type}"
  end

  encrypted = Privy::Cryptography::HpkeSender.new.encrypt(
    Base64.strict_decode64(init_response.encryption_public_key),
    private_key_bytes
  )

  submit_params = {
    wallet: import_wallet.merge(
      encryption_type: "HPKE",
      encapsulated_key: Base64.strict_encode64(encrypted.encapsulated_key),
      ciphertext: Base64.strict_encode64(encrypted.ciphertext)
    ),
    request_options: request_options
  }
  {
    additional_signers: additional_signers,
    display_name: display_name,
    external_id: external_id,
    owner: owner,
    owner_id: owner_id,
    policy_ids: policy_ids
  }.each do |key, value|
    submit_params[key] = value unless value.nil?
  end

  _submit_import(submit_params)
end

#raw_sign(wallet_id, raw_sign_input:, authorization_context: nil, idempotency_key: nil, request_expiry: nil, request_options: nil) ⇒ Privy::Models::RawSignResponse

Sign a hash or raw bytes with a wallet by wallet ID.

Examples:

Sign a pre-computed hash

client.wallets.raw_sign("wallet-id", raw_sign_input: {
  params: {hash: "0x1234...abcdef"}
})

Sign raw bytes with a hash function

client.wallets.raw_sign("wallet-id", raw_sign_input: {
  params: {bytes: "0a0234ea...", encoding: "hex", hash_function: "sha256"}
}, authorization_context: ctx)

Parameters:

  • wallet_id (String)

    ID of the wallet to sign with.

  • raw_sign_input (Hash)

    Body parameters for the raw_sign operation (RawSignInput shape).

  • authorization_context (Privy::Authorization::AuthorizationContext, nil) (defaults to: nil)

    Authorization context for owned wallets.

  • idempotency_key (String, nil) (defaults to: nil)

    Ensures the request is executed only once.

  • request_expiry (Integer, nil) (defaults to: nil)

    Absolute Unix-ms timestamp at which the request expires. Defaults to the value computed by the client’s PrivyRequestExpiryOptions.

  • request_options (Privy::RequestOptions, Hash, nil) (defaults to: nil)

    Transport-level config (timeouts, retries).

Options Hash (raw_sign_input:):

  • :params (Hash)

    The signing parameters (required). Either hash: or encoding:, hash_function:.

Returns:



229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
# File 'lib/privy/public_api/services/wallets.rb', line 229

def raw_sign(
  wallet_id,
  raw_sign_input:,
  authorization_context: nil,
  idempotency_key: nil,
  request_expiry: nil,
  request_options: nil
)
  prepared = Privy::Authorization.prepare_request(
    privy_client,
    method: :post,
    url: Privy::Authorization.signed_url(privy_client, "v1/wallets/#{wallet_id}/raw_sign"),
    body: raw_sign_input,
    authorization_context: authorization_context,
    idempotency_key: idempotency_key,
    request_expiry: privy_client.compute_request_expiry(request_expiry)
  )
  combined_params = raw_sign_input.merge(request_options: request_options)
  Privy::Authorization.merge_prepared_headers!(combined_params, prepared.headers)
  super(wallet_id, combined_params)
end

#rpc(wallet_id, wallet_rpc_request_body:, authorization_context: nil, idempotency_key: nil, request_expiry: nil, request_options: nil) ⇒ Privy::Models::WalletRpcResponse

Sign a message or transaction with a wallet by wallet ID.

Examples:

Personal sign on an ownerless wallet

client.wallets.rpc("wallet-id", wallet_rpc_request_body: {
  method: "personal_sign",
  chain_type: "ethereum",
  params: {message: "hello", encoding: "utf-8"}
})

Sign a transaction with authorization

client.wallets.rpc("wallet-id", wallet_rpc_request_body: {
  method: "eth_signTransaction",
  chain_type: "ethereum",
  params: {transaction: {to: "0x...", value: "0x0", chain_id: 1}}
}, authorization_context: ctx)

Parameters:

  • wallet_id (String)

    ID of the wallet.

  • wallet_rpc_request_body (Hash)

    The RPC request body, discriminated by :method.

  • authorization_context (Privy::Authorization::AuthorizationContext, nil) (defaults to: nil)

    Authorization context for owned wallets.

  • idempotency_key (String, nil) (defaults to: nil)

    Ensures the request is executed only once.

  • request_expiry (Integer, nil) (defaults to: nil)

    Absolute Unix-ms timestamp at which the request expires. Defaults to the value computed by the client’s PrivyRequestExpiryOptions.

  • request_options (Privy::RequestOptions, Hash, nil) (defaults to: nil)

    Transport-level config (timeouts, retries).

Options Hash (wallet_rpc_request_body:):

  • :method (String)

    The RPC method name (e.g. “personal_sign”, “eth_signTransaction”).

  • :chain_type (String)

    The chain type (e.g. “ethereum”, “solana”).

  • :params (Hash)

    Method-specific parameters.

Returns:



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/privy/public_api/services/wallets.rb', line 184

def rpc(
  wallet_id,
  wallet_rpc_request_body:,
  authorization_context: nil,
  idempotency_key: nil,
  request_expiry: nil,
  request_options: nil
)
  prepared = Privy::Authorization.prepare_request(
    privy_client,
    method: :post,
    url: Privy::Authorization.signed_url(privy_client, "v1/wallets/#{wallet_id}/rpc"),
    body: wallet_rpc_request_body,
    authorization_context: authorization_context,
    idempotency_key: idempotency_key,
    request_expiry: privy_client.compute_request_expiry(request_expiry)
  )
  combined_params = {wallet_rpc_request_body: wallet_rpc_request_body, request_options: request_options}
  Privy::Authorization.merge_prepared_headers!(combined_params, prepared.headers)
  super(wallet_id, combined_params)
end

#transfer(wallet_id, wallet_transfer_params:, authorization_context: nil, idempotency_key: nil, request_expiry: nil, request_options: nil) ⇒ Privy::Models::TransferActionResponse

Transfer tokens from a wallet to a destination address.

Examples:

Transfer USDC on Base

client.wallets.transfer("wallet-id", wallet_transfer_params: {
  source: {asset: "usdc", amount: "10.5", chain: "base"},
  destination: {address: "0xB00F...28a2"}
})

Cross-asset transfer with slippage

client.wallets.transfer("wallet-id", wallet_transfer_params: {
  source: {asset: "usdc", amount: "10.5", chain: "base"},
  destination: {address: "0xB00F...28a2", asset: "usdt", chain: "ethereum"},
  amount_type: "exact_input",
  slippage_bps: 100
}, authorization_context: ctx)

Parameters:

  • wallet_id (String)

    ID of the wallet to transfer from.

  • wallet_transfer_params (Hash)

    Body parameters for the transfer operation.

  • authorization_context (Privy::Authorization::AuthorizationContext, nil) (defaults to: nil)

    Authorization context for owned wallets.

  • idempotency_key (String, nil) (defaults to: nil)

    Ensures the request is executed only once.

  • request_expiry (Integer, nil) (defaults to: nil)

    Absolute Unix-ms timestamp at which the request expires. Defaults to the value computed by the client’s PrivyRequestExpiryOptions.

  • request_options (Privy::RequestOptions, Hash, nil) (defaults to: nil)

    Transport-level config (timeouts, retries).

Options Hash (wallet_transfer_params:):

  • :source (Hash)

    Source asset, amount, and chain (required).

  • :destination (Hash)

    Destination address, and optionally asset and chain (required).

  • :amount_type (String)

    Whether amount refers to input or output token (“exact_input” or “exact_output”).

  • :slippage_bps (Integer)

    Maximum allowed slippage in basis points (1 bps = 0.01%).

Returns:



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/privy/public_api/services/wallets.rb', line 281

def transfer(
  wallet_id,
  wallet_transfer_params:,
  authorization_context: nil,
  idempotency_key: nil,
  request_expiry: nil,
  request_options: nil
)
  prepared = Privy::Authorization.prepare_request(
    privy_client,
    method: :post,
    url: Privy::Authorization.signed_url(privy_client, "v1/wallets/#{wallet_id}/transfer"),
    body: wallet_transfer_params,
    authorization_context: authorization_context,
    idempotency_key: idempotency_key,
    request_expiry: privy_client.compute_request_expiry(request_expiry)
  )
  combined_params = wallet_transfer_params.merge(request_options: request_options)
  Privy::Authorization.merge_prepared_headers!(combined_params, prepared.headers)
  _transfer(wallet_id, combined_params)
end

#update(wallet_id, wallet_update_params:, authorization_context: nil, request_expiry: nil, request_options: nil) ⇒ Privy::Models::Wallet

Update a wallet’s policies or authorization key configuration.

Examples:

Update wallet policies

client.wallets.update("wallet-id", wallet_update_params: {
  policy_ids: ["policy-id"]
}, authorization_context: ctx)

Parameters:

  • wallet_id (String)

    ID of the wallet to update.

  • wallet_update_params (Hash)

    Body parameters for the update.

  • authorization_context (Privy::Authorization::AuthorizationContext, nil) (defaults to: nil)

    Authorization context for owned wallets.

  • request_expiry (Integer, nil) (defaults to: nil)

    Absolute Unix-ms timestamp at which the request expires. Defaults to the value computed by the client’s PrivyRequestExpiryOptions.

  • request_options (Privy::RequestOptions, Hash, nil) (defaults to: nil)

    Transport-level config (timeouts, retries).

Options Hash (wallet_update_params:):

  • :owner (Hash, nil)

    New owner specified as user_id: or public_key:.

  • :owner_id (String, nil)

    Key quorum ID to set as owner.

  • :policy_ids (Array<String>, nil)

    New policy IDs to enforce on the wallet.

  • :display_name (String, nil)

    A human-readable label for the wallet. Set to nil to clear.

  • :additional_signers (Array<Hash>, nil)

    Additional signers for the wallet.

Returns:



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/privy/public_api/services/wallets.rb', line 135

def update(
  wallet_id,
  wallet_update_params:,
  authorization_context: nil,
  request_expiry: nil,
  request_options: nil
)
  prepared = Privy::Authorization.prepare_request(
    privy_client,
    method: :patch,
    url: Privy::Authorization.signed_url(privy_client, "v1/wallets/#{wallet_id}"),
    body: wallet_update_params,
    authorization_context: authorization_context,
    request_expiry: privy_client.compute_request_expiry(request_expiry)
  )
  combined_params = wallet_update_params.merge(request_options: request_options)
  Privy::Authorization.merge_prepared_headers!(combined_params, prepared.headers)
  super(wallet_id, combined_params)
end