Обработка учетных записей и транзакций подписей с nearlib - PullRequest
1 голос
/ 30 октября 2019

У меня есть контракт, который называется 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, и здесь снова возникает вопрос: возможно ли это, и если да, то как?

1 Ответ

1 голос
/ 31 октября 2019

Короткий ответ

Вы должны использовать env::predecessor_account_id() для получения идентификатора учетной записи пользователя или контракта, который вызвал метод обмена.

Подробности

В вашемВ этом случае даже через ключевые точки доступа в направлении exchange он все еще подписан bob. The signer_id and the priorcessor_id during the execution are both going to be bob`.

Во время выполнения существует 3 различных типа учетных записей:

  • env::current_account_id() возвращает идентификатор текущей учетной записи контракта, который выполняется прямо сейчас.
  • env::signer_account_id() возвращает идентификатор учетной записи пользователя, подписавшего исходную транзакцию. В большинстве случаев вам никогда не следует полагаться на идентификатор учетной записи подписавшего, поскольку текущий вызов может быть выполнен из другого контракта.
  • env::predecessor_account_id() возвращает идентификатор учетной записи непосредственного предшественника, который вызвал текущий контракт. Вы должны использовать его для проверки личности пользователя, который вам звонил.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...