У меня есть контракт, который называется exchange
. Пользователь, Bob
, хочет потратить near tokens
на покупку позиций в markets
посредством размещения Order
. Order
имеет поле с именем owner
, важно, чтобы в договоре было доказательство того, что определенному order
принадлежит определенный адрес, в данном случае Bob
.
То, как в настоящий момент обрабатываются транзакции, отправляемые на exchange
, представляет собой поток, аналогичный:
const init = async () => {
this.near = await window.nearlib.connect(Object.assign({ deps: { keyStore: new window.nearlib.keyStores.BrowserLocalStorageKeyStore() } }, window.nearConfig));
this.walletAccount = new window.nearlib.WalletAccount(this.near);
this.accountId = this.walletAccount.getAccountId();
this.exchange = await this.near.loadContract(window.nearConfig.contractName, {
viewMethods: [],
changeMethods: ["place_new_order"],
sender: this.accountId,
});
}
await init();
// Bob logs into to near
this.walletAccount.requestSignIn(
window.nearConfig.contractName,
window.nearConfig.contractName,
);
// Login process
[...]
// Bob wants to place a new order
this.exchange.place_new_order(price, amount);
Контракт exchange
импортирует struct
с именем Order
.
Order
будет выглядеть так:
use std::string::String;
use borsh::{BorshDeserialize, BorshSerialize};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, BorshDeserialize, BorshSerialize, Clone)]
pub struct Order {
pub owner: String,
pub amount: u64,
pub price: u64,
}
impl Order {
pub fn new(owner: String, amount: u64, price: u64) -> Self {
Order {
owner,
amount,
price
}
}
}
Exchange
, в данном случае, это контракт, который реализует мод order
. Exchange
имеет метод place_new_order
, где я хочу быть в состоянии убедиться, что Bob
- это тот, кто отправил транзакцию:
use near_bindgen::{near_bindgen, env};
[...]
mod Order;
[...]
pub fn place_new_order(&mut self, amount: u64, price: u64) {
// Stuff happens here
let order = Order::new(env::current_account_id(), amount, price);
// Stuff happens here
}
Теперь дело в том, что при использованииэтот код ближней библиотеки env::current_account_id()
всегда будет возвращать exchange
как current_account_id
. Это имеет смысл, потому что все, что делает логин, это создает access_key
, который позволяет exchange
делать пару вещей от имени Bob
, но при этом все равно Exchange
подписывает транзакции.
вопрос здесь: как я могу убедиться, что обмен знает, что Bob
- это тот, кто инициализировал транзакцию?
Способ, которым это может работать, имеет смысл:
Bob
подписывает каждую транзакцию своим закрытым ключом, и у меня возникает следующий вопрос: как?
Это может вызвать метамасковую проблему UX, когда отмена подписи на каждом tx - плохой UX.
Я бы предложил следующее:
Bob
использует метод deposit
для внесения установленной суммы near-tokens
на exchange
и exchange
разрешено тратить это до тех пор, пока он может доказать, что он делает это через «login-access-token», подписанный Bob
, и здесь снова возникает вопрос: возможно ли это, и если да, то как?