Peatio submits all events into three exchanges depending on event category (read next).
The exchange name consists of three parts:
1) application name, like peatio
, barong
.
2) fixed keyword events
.
3) category of event, like system
(generic system event), model
(the attributes of some record were updated), market
(trading events).
The routing key looks like deposit.updated
, btcusd.new_order
.
The event name matches the routing key but with event category appended at the beginning, like model.deposit.updated
, market.btcusd.new_order
.
Each produced message in Event API
is JWT (complete format).
This is very similar to Management API
.
The example below demonstrates both generation and verification of JWT:
require "jwt-multisig"
require "securerandom"
jwt_payload = {
iss: "peatio",
jti: SecureRandom.uuid,
iat: Time.now.to_i,
exp: Time.now.to_i + 60,
event: {}
}
require "openssl"
private_key = OpenSSL::PKey::RSA.generate(2048)
public_key = private_key.public_key
generated_jwt = JWT::Multisig.generate_jwt(jwt_payload, { peatio: private_key }, { peatio: "RS256" })
Kernel.puts "GENERATED JWT", generated_jwt.to_json, "\n"
verification_result = JWT::Multisig.verify_jwt generated_jwt.deep_stringify_keys, \
{ peatio: public_key }, { verify_iss: true, iss: "peatio", verify_jti: true }
decoded_jwt_payload = verification_result[:payload]
Kernel.puts "MATCH AFTER VERIFICATION: #{jwt_payload == decoded_jwt_payload}."
The RabbitMQ message is stored in JWT field called event
.
The typical event looks like (JSON):
event: {
name: "model.deposit.updated",
foo: "...",
bar: "...",
qux: "..."
}
The field event[:name]
contains event name (same as routing key).
The fields foo
, bar
, qux
(just for example) are fields which carry useful information.
model.deposit.created
eventevent: {
name: "model.deposit.created",
record: {
tid: "TID9493F6CD41",
user: {
uid: "ID092B2AF8E87",
email: "[email protected]"
},
uid: "ID092B2AF8E87",
currency: "btc",
amount: "0.0855",
state: "submitted",
created_at: "2018-04-12T17:16:06+03:00",
updated_at: "2018-04-12T17:16:06+03:00",
completed_at: nil,
blockchain_address: "n1Ytj6Hy57YpfueA2vtmnwJQs583bpYn7W",
blockchain_txid: "c37ae1677c4c989dbde9ac22be1f3ff3ac67ed24732a9fa8c9258fdff0232d72",
blockchain_confirmations: 1
}
}
Field | Description |
---|---|
record | The up-to-date deposit attributes. |
model.deposit.updated
eventevent: {
name: "model.deposit.updated",
record: {
tid: "TID9493F6CD41",
user: {
uid: "ID092B2AF8E87",
email: "[email protected]"
},
uid: "ID092B2AF8E87",
currency: "btc",
amount: "0.0855",
state: "accepted",
created_at: "2018-04-12T17:16:06+03:00",
updated_at: "2018-04-12T18:46:57+03:00",
completed_at: "2018-04-12T18:46:57+03:00",
blockchain_address: "n1Ytj6Hy57YpfueA2vtmnwJQs583bpYn7W",
blockchain_txid: "c37ae1677c4c989dbde9ac22be1f3ff3ac67ed24732a9fa8c9258fdff0232d72",
blockchain_confirmations: 7
},
changes: {
state: "submitted",
completed_at: nil,
blockchain_confirmations: 1,
updated_at: "2018-04-12T17:16:06+03:00"
}
}
Field | Description |
---|---|
record | The up-to-date deposit attributes. |
changes | The changed deposit attributes and their values. |
model.withdraw.created
eventevent: {
name: "model.withdraw.created",
record: {
tid: "TID892F29F094",
user: {
uid: "ID092B2AF8E87",
email: "[email protected]"
},
uid: "ID092B2AF8E87",
rid: "0xdA35deE8EDDeAA556e4c26268463e26FB91ff74f",
currency: "eth",
amount: "4.5485",
fee: "0.0015",
state: "prepared",
created_at: "2018-04-12T18:52:16+03:00",
updated_at: "2018-04-12T18:52:16+03:00",
completed_at: nil,
blockchain_txid: nil
}
}
Field | Description |
---|---|
record | The up-to-date withdraw attributes. |
model.withdraw.updated
eventevent: {
name: "model.withdraw.updated",
record: {
tid: "TID892F29F094",
user: {
uid: "ID092B2AF8E87",
email: "[email protected]"
},
uid: "ID092B2AF8E87",
rid: "0xdA35deE8EDDeAA556e4c26268463e26FB91ff74f",
currency: "eth",
amount: "4.5485",
fee: "0.0015",
state: "succeed",
created_at: "2018-04-12T18:52:16+03:00",
updated_at: "2018-04-12T18:56:23+03:00",
completed_at: "2018-04-12T18:56:23+03:00",
blockchain_txid: "0x9c34d1750e225a95938f9884e857ab6f55eedda43b159d13abf773fe6a916164"
},
changes: {
state: "processing",
updated_at: "2018-04-12T18:55:39+03:00",
completed_at: "2018-04-12T18:55:39+03:00",
blockchain_txid: nil
}
}
Field | Description |
---|---|
record | The up-to-date withdraw attributes. |
changes | The changed withdraw attributes and their values. |
model.account.created
eventevent: {
name: "model.account.created",
record: {
id: "1",
member_id: "2",
currency_id: "btc",
balance: "0",
locked: "0",
created_at: "2018-04-12T17:16:06+03:00",
updated_at: "2018-04-12T17:16:06+03:00",
}
}
Field | Description |
---|---|
record | The up-to-date account attributes. |
model.account.updated
eventevent: {
name: "model.account.updated",
record: {
id: "1",
member_id: "2",
currency_id: "btc",
balance: "1",
locked: "0",
created_at: "2018-04-12T17:16:06+03:00",
updated_at: "2018-04-12T17:17:06+03:00",
},
changes: {
balance: "0",
updated_at: "2018-04-12T17:16:06+03:00"
}
}
Field | Description |
---|---|
record | The up-to-date account attributes. |
changes | The changed account attributes and their values. |
system.low_hot_wallet_balance
eventevent: {
name: "system.system.low_hot_wallet_balance",
currency: "btc",
balance: "2.82480099"
}
Field | Description |
---|---|
currency | The currency code. |
balance | The up-to-date balance. |
market.btcusd.order_created
eventBuy 14 BTC for 0.42 USD (0.03 USD per BTC).
event: {
name: "market.btcusd.order_created",
market: "btcusd",
type: "buy",
trader_uid: "ID022H2NF6E87",
income_unit: "btc",
income_fee_type: "relative",
income_fee_value: "0.0015",
outcome_unit: "usd",
outcome_fee_type: "relative",
outcome_fee_value: "0.0",
initial_income_amount: "14.0",
current_income_amount: "14.0",
initial_outcome_amount: "0.42",
current_outcome_amount: "0.42",
strategy: "limit",
price: "0.03",
state: "open",
trades_count: 0,
created_at: "2018-05-07T02:12:28Z"
}
market.btcusd.order_updated
eventSell 100 BTC for 3 USD (0.03 USD per BTC).
event: {
name: "market.btcusd.order_updated",
market: "btcusd",
type: "sell",
trader_uid: "ID092B2AF8E87",
income_unit: "usd",
income_fee_type: "relative",
income_fee_value: "0.0015",
outcome_unit: "btc",
outcome_fee_type: "relative",
outcome_fee_value: "0.0",
initial_income_amount: "3.0",
current_income_amount: "2.4",
previous_income_amount: "3.0",
initial_outcome_amount: "100.0",
current_outcome_amount: "80.0",
previous_outcome_amount: "100.0",
strategy: "limit",
price: "0.03",
state: "open",
trades_count: 1,
created_at: "2018-05-07T02:12:28Z",
updated_at: "2018-05-08T10:13:13Z"
}
market.btcusd.order_canceled
eventSell 100 BTC for 3 USD (0.03 USD per BTC).
event: {
name: "market.btcusd.order_canceled",
market: "btcusd",
type: "sell",
trader_uid: "ID092B2AF8E87",
income_unit: "usd",
income_fee_type: "relative",
income_fee_value: "0.0015",
outcome_unit: "btc",
outcome_fee_type: "relative",
outcome_fee_value: "0.0",
initial_income_amount: "3.0",
current_income_amount: "3.0",
initial_outcome_amount: "100.0",
current_outcome_amount: "100.0",
strategy: "limit",
price: "0.03",
state: "canceled",
trades_count: 0,
created_at: "2018-05-07T02:12:28Z",
canceled_at: "2018-05-08T10:13:13Z"
}
market.btcusd.order_completed
eventSell 100 BTC for 3 USD (0.03 USD per BTC).
event: {
name: "market.btcusd.order_completed",
market: "btcusd",
type: "sell",
trader_uid: "ID092B2AF8E87",
income_unit: "usd",
income_fee_type: "relative",
income_fee_value: "0.0015",
outcome_unit: "btc",
outcome_fee_type: "relative",
outcome_fee_value: "0.0",
initial_income_amount: "3.0",
current_income_amount: "0.0",
previous_income_amount: "3.0",
initial_outcome_amount: "100.0",
current_outcome_amount: "0.0",
previous_outcome_amount: "100.0",
strategy: "limit",
price: "0.03",
state: "completed",
trades_count: 1,
created_at: "2018-05-07T02:12:28Z",
completed_at: "2018-05-07T17:32:09Z"
}
market.btcusd.trade_completed
eventevent: {
name: "market.btcusd.trade_completed",
market: "btcusd",
price: "0.03",
buyer_uid: "ID022H2NF6E87",
buyer_income_unit: "btc",
buyer_income_amount: "14",
buyer_income_fee: "0.021",
buyer_outcome_unit: "usd",
buyer_outcome_amount: "0.42",
buyer_outcome_fee: "0.0",
seller_uid: "ID092B2AF8E87",
seller_income_unit: "usd",
seller_income_amount: "0.42",
seller_income_fee: "0.00063",
seller_outcome_unit: "btc",
seller_outcome_amount: "14.0",
seller_outcome_fee: "0.0",
completed_at: "2018-05-07T17:32:09Z"
}
require "bunny"
def generate_jwt(jwt_payload)
Kernel.abort "Please, see «Overview of RabbitMQ message» for implementation guide."
end
Bunny.run host: "localhost", port: 5672, username: "guest", password: "guest" do |session|
channel = session.channel
exchange = channel.direct("peatio.events.model")
jwt_payload = {
iss: "peatio",
jti: SecureRandom.uuid,
iat: Time.now.to_i,
exp: Time.now.to_i + 60,
event: {
name: "model.deposit.created",
record: {
tid: "TID9493F6CD41",
user: {
uid: "ID092B2AF8E87",
email: "[email protected]"
},
uid: "ID092B2AF8E87",
currency: "btc",
amount: "0.0855",
state: "submitted",
created_at: "2018-04-12T17:16:06+03:00",
updated_at: "2018-04-12T17:16:06+03:00",
completed_at: nil,
blockchain_address: "n1Ytj6Hy57YpfueA2vtmnwJQs583bpYn7W",
blockchain_txid: "c37ae1677c4c989dbde9ac22be1f3ff3ac67ed24732a9fa8c9258fdff0232d72",
blockchain_confirmations: 1
}
}
}
exchange.publish(generate_jwt(jwt_payload), routing_key: "deposit.created")
end
IMPORTANT: Don't forget to implement the logic for JWT exception handling!
rabbitmqadmin
rabbitmqadmin publish routing_key=deposit.created payload=JWT exchange=peatio.events.model
Don't forget to pass environment variable JWT
.
require "bunny"
def verify_jwt(jwt_payload)
Kernel.abort "Please, see «Overview of RabbitMQ message» for implementation guide."
end
Bunny.run host: "localhost", port: 5672, username: "guest", password: "guest" do |session|
channel = session.channel
exchange = channel.direct("peatio.events.model")
queue = channel.queue("", auto_delete: true, durable: true, exclusive: true)
.bind(exchange, routing_key: "deposit.updated")
queue.subscribe manual_ack: true, block: true do |delivery_info, metadata, payload|
Kernel.puts verify_jwt(JSON.parse(payload)).fetch(:event)
channel.ack(delivery_info.delivery_tag)
rescue => e
channel.nack(delivery_info.delivery_tag, false, true)
end
end
IMPORTANT: Don't forget to implement the logic for JWT exception handling!