Class: Coinbase::StakingOperation

Inherits:
Object
  • Object
show all
Defined in:
lib/coinbase/staking_operation.rb

Overview

A representation of a staking operation (stake, unstake, claim rewards, etc). It may have multiple steps with some being transactions to sign, and others to wait.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model) ⇒ StakingOperation

Returns a new StakingOperation object.

Parameters:



91
92
93
94
95
# File 'lib/coinbase/staking_operation.rb', line 91

def initialize(model)
  @model = model
  @transactions ||= []
  update_transactions(model.transactions)
end

Instance Attribute Details

#statusSymbol (readonly)

Returns the status of the Staking Operation.

Returns:

  • (Symbol)

    The status



9
10
11
# File 'lib/coinbase/staking_operation.rb', line 9

def status
  @status
end

#transactionsArray<Coinbase::Transaction> (readonly)

The list of current transactions associated with the operation.

Returns:



9
10
11
# File 'lib/coinbase/staking_operation.rb', line 9

def transactions
  @transactions
end

Class Method Details

.build(amount, network, asset_id, address_id, action, mode, options) ⇒ Coinbase::StakingOperation

Builds an ephemeral staking operation this is intended to be called via an Address or Wallet.

Parameters:

  • amount (BigDecimal)

    The amount to stake, in the primary denomination of the asset

  • network (Coinbase::Network, Symbol)

    The Network or Network ID

  • asset_id (Symbol)

    The Asset ID

  • address_id (String)

    The Address ID

  • action (Symbol)

    The action to perform

  • mode (Symbol)

    The staking mode

  • options (Hash)

    Additional options

Returns:



21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/coinbase/staking_operation.rb', line 21

def self.build(amount, network, asset_id, address_id, action, mode, options)
  network = Coinbase::Network.from_id(network)
  asset = network.get_asset(asset_id)

  model = Coinbase.call_api do
    stake_api.build_staking_operation(
      {
        asset_id: asset.primary_denomination.to_s,
        address_id: address_id,
        action: action,
        network_id: Coinbase.normalize_network(network),
        options: {
          amount: asset.to_atomic_amount(amount).to_i.to_s,
          mode: mode
        }.merge(options)
      }
    )
  end

  new(model)
end

.create(amount, network, asset_id, address_id, wallet_id, action, mode, options) ⇒ Coinbase::StakingOperation

Creates a persisted staking operation this is intended to be called via an Address or Wallet.

Parameters:

  • amount (BigDecimal)

    The amount to stake, in the primary denomination of the asset

  • network (Coinbase::Network, Symbol)

    The Network or Network ID

  • asset_id (Symbol)

    The Asset ID

  • address_id (String)

    The Address ID

  • wallet_id (String)

    The Wallet ID

  • action (Symbol)

    The action to perform

  • mode (Symbol)

    The staking mode

  • options (Hash)

    Additional options

Returns:



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/coinbase/staking_operation.rb', line 53

def self.create(amount, network, asset_id, address_id, wallet_id, action, mode, options)
  network = Coinbase::Network.from_id(network)
  asset = network.get_asset(asset_id)

  model = Coinbase.call_api do
    wallet_stake_api.create_staking_operation(
      wallet_id,
      address_id,
      {
        asset_id: asset.primary_denomination.to_s,
        address_id: address_id,
        action: action,
        network_id: Coinbase.normalize_network(network),
        options: {
          amount: asset.to_atomic_amount(amount).to_i.to_s,
          mode: mode
        }.merge(options)
      }
    )
  end

  new(model)
end

.fetch(network, address_id, id, wallet_id: nil) ⇒ Coinbase::StakingOperation

Fetch the StakingOperation with the provided network, address and staking operation ID.

Parameters:

  • network (Coinbase::Network, Symbol)

    The Network or Network ID

  • address_id (Symbol)

    The Address ID

  • id (String)

    The ID of the StakingOperation

  • wallet_id (String) (defaults to: nil)

    The optional Wallet ID

Returns:



224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/coinbase/staking_operation.rb', line 224

def self.fetch(network, address_id, id, wallet_id: nil)
  network = Coinbase::Network.from_id(network)

  staking_operation_model = Coinbase.call_api do
    if wallet_id.nil?
      stake_api.get_external_staking_operation(network.id, address_id, id)
    else
      wallet_stake_api.get_staking_operation(wallet_id, address_id, id)
    end
  end

  new(staking_operation_model)
end

Instance Method Details

#address_idString

Returns the Address ID of the Staking Operation.

Returns:

  • (String)

    The Address ID



111
112
113
# File 'lib/coinbase/staking_operation.rb', line 111

def address_id
  @model.address_id
end

#broadcast!Coinbase::StakingOperation

Broadcasts the Staking Operation transactions to the network



279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
# File 'lib/coinbase/staking_operation.rb', line 279

def broadcast!
  transactions.each_with_index do |transaction, i|
    raise TransactionNotSignedError unless transaction.signed?

    Coinbase.call_api do
      wallet_stake_api.broadcast_staking_operation(
        wallet_id,
        address_id,
        id,
        { signed_payload: transaction.raw.hex, transaction_index: i }
      )
    end
  end

  self
end

#complete(key, interval_seconds: 5, timeout_seconds: 600) ⇒ StakingOperation

Complete helps the Staking Operation reach complete state, by polling its status at the given interval, signing and broadcasting any available transaction.

Parameters:

  • key (Eth::Key)

    The key to sign the Staking Operation transactions with

  • interval_seconds (Integer) (defaults to: 5)

    The interval at which to poll, in seconds

  • timeout_seconds (Integer) (defaults to: 600)

    The maximum amount of time to wait for the StakingOperation to complete, in seconds

Returns:

Raises:

  • (Timeout::Error)

    if the Staking Operation takes longer than the given timeout.



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/coinbase/staking_operation.rb', line 188

def complete(key, interval_seconds: 5, timeout_seconds: 600)
  start_time = Time.now

  loop do
    @transactions.each_with_index do |transaction, i|
      next if transaction.signed?

      transaction.sign(key)
      @model = Coinbase.call_api do
        stake_api.broadcast_staking_operation(
          wallet_id,
          address_id,
          id,
          { signed_payload: transaction.raw.hex, transaction_index: i }
        )
      end
    end

    return self if terminal_state?

    reload

    raise Timeout::Error, 'Staking Operation timed out' if Time.now - start_time > timeout_seconds

    sleep interval_seconds
  end

  self
end

#completed?Boolean

Returns whether the Staking Operation is in a complete state.

Returns:

  • (Boolean)

    Whether the Staking Operation is in a complete state



135
136
137
# File 'lib/coinbase/staking_operation.rb', line 135

def completed?
  status == 'complete'
end

#failed?Boolean

Returns whether the Staking Operation is in a failed state.

Returns:

  • (Boolean)

    Whether the Staking Operation is in a failed state



129
130
131
# File 'lib/coinbase/staking_operation.rb', line 129

def failed?
  status == 'failed'
end

#idString

Returns the Staking Operation ID.

Returns:

  • (String)

    The Staking Operation ID



99
100
101
# File 'lib/coinbase/staking_operation.rb', line 99

def id
  @model.id
end

#networkCoinbase::Network

Returns the Network of the Staking Operation.

Returns:



105
106
107
# File 'lib/coinbase/staking_operation.rb', line 105

def network
  @network ||= Coinbase::Network.from_id(@model.network_id)
end

#reloadCoinbase::StakingOperation

Reloads the staking_operation from the service

Returns:



248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/coinbase/staking_operation.rb', line 248

def reload
  @model = Coinbase.call_api do
    if wallet_id.nil?
      stake_api.get_external_staking_operation(network.id, address_id, id)
    else
      wallet_stake_api.get_staking_operation(wallet_id, address_id, id)
    end
  end

  update_transactions(@model.transactions)

  self
end

#sign(key) ⇒ Object

Signs the Open Transactions with the provided key

Parameters:

  • key (Eth::Key)

    The key to sign the transactions with



240
241
242
243
244
# File 'lib/coinbase/staking_operation.rb', line 240

def sign(key)
  transactions.each do |transaction|
    transaction.sign(key) unless transaction.signed?
  end
end

#signed_voluntary_exit_messagesArray<string>

Fetches the presigned_voluntary exit messages for the staking operation

Returns:

  • (Array<string>)

    The list of presigned exit transaction messages



264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/coinbase/staking_operation.rb', line 264

def signed_voluntary_exit_messages
  return [] unless @model.

  signed_voluntary_exit_messages = []

  @model..each do ||
    decoded_string = Base64.decode64(.signed_voluntary_exit)
    signed_voluntary_exit_messages.push(decoded_string)
  end

  signed_voluntary_exit_messages
end

#terminal_state?Boolean

Returns whether the Staking Operation is in a terminal state.

Returns:

  • (Boolean)

    Whether the Staking Operation is in a terminal state



123
124
125
# File 'lib/coinbase/staking_operation.rb', line 123

def terminal_state?
  failed? || completed?
end

#to_sString

Returns a String representation of the Staking Operation.

Returns:

  • (String)

    a String representation of the Staking Operation



141
142
143
144
145
146
147
148
149
# File 'lib/coinbase/staking_operation.rb', line 141

def to_s
  Coinbase.pretty_print_object(
    self.class,
    id: id,
    status: status,
    network_id: network.id,
    address_id: address_id
  )
end

#wait!(interval_seconds = 5, timeout_seconds = 3600) ⇒ StakingOperation

Waits until the Staking Operation is completed or failed by polling its status at the given interval.

Parameters:

  • interval_seconds (Integer) (defaults to: 5)

    The interval at which to poll, in seconds

  • timeout_seconds (Integer) (defaults to: 3600)

    The maximum amount of time to wait for the StakingOperation to complete, in seconds

Returns:

Raises:

  • (Timeout::Error)

    if the Staking Operation takes longer than the given timeout.



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
# File 'lib/coinbase/staking_operation.rb', line 163

def wait!(interval_seconds = 5, timeout_seconds = 3600)
  start_time = Time.now

  loop do
    reload

    # Wait for the Staking Operation to be in a terminal state.
    break if terminal_state?

    raise Timeout::Error, 'Staking Operation timed out' if Time.now - start_time > timeout_seconds

    self.sleep interval_seconds
  end

  self
end

#wallet_idString

Returns the Wallet ID of the Staking Operation.

Returns:

  • (String)

    The Wallet ID



153
154
155
# File 'lib/coinbase/staking_operation.rb', line 153

def wallet_id
  @model.wallet_id
end