All files / zkapp BasicRequestClient.ts

100% Statements 42/42
100% Branches 0/0
100% Functions 14/14
100% Lines 39/39

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 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 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 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 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244                                                              1x 1x   1x 2x                                             1x 1x   1x 2x                                   1x 1x   1x 2x 2x                                   70x           70x           70x                     6x     6x                 2x 13x                 2x 10x                         2x                   10x 10x                       2x           10x 10x   10x 10x                         2x           10x 10x   10x 10x   10x 10x                                 2x   19x      
import {
  Bool,
  Encoding,
  Field,
  PublicKey,
  SmartContract,
  State,
  method,
  state,
  Mina,
  UInt64, AccountUpdate,
} from 'o1js';
import { OracleContract, IOracleClient } from './OracleContract.js';
import { OracleRequest } from '../gen/oracle-request_pb.js';
import { buildERC677Contract, SErc677Contract } from '../token/Erc677Token.js';
 
/**
 * Builds a Mina transaction that sends an Oracle request to a designated zkApp with Addr.
 *
 * @param {Mina.FeePayerSpec} sender - The fee payer specification for the transaction.
 * @param {PublicKey} oracleAddress - The Oracle contract address to use.
 * @param {SmartContract & IOracleClient} zkApp - The zkApp contract that accepts Oracle requests, also implementing the `IOracleClient` interface.
 * @param {OracleRequest} oracleRequest - The data for the Oracle request, represented as an `OracleRequest` object.
 * @returns {Promise<Mina.Transaction>} - A promise that resolves to a Mina transaction containing the Oracle request.
 */
export async function buildOracleRequestTxWithAddr(
  sender: Mina.FeePayerSpec,
  oracleAddress: PublicKey,
  zkApp: SmartContract & IOracleClient,
  oracleRequest: OracleRequest
): Promise<Mina.Transaction<false,false>> {
  const offChainBytes = oracleRequest.toBinary(); // Convert request data to binary
  const reqField = Encoding.bytesToFields(offChainBytes); // Convert binary to fields
 
  return Mina.transaction(sender, async () => {
    await zkApp.sendOracleRequestWithAddr(
      oracleAddress,
      reqField[0],
      reqField[1],
      reqField[2],
      reqField[3]
    );
  });
}
 
/**
 * Builds a Mina transaction that sends an Oracle request to a designated zkApp.
 *
 * @param {Mina.FeePayerSpec} sender - The fee payer specification for the transaction.
 * @param {SmartContract & IOracleClient} zkApp - The zkApp contract that accepts Oracle requests, also implementing the `IOracleClient` interface.
 * @param {OracleRequest} oracleRequest - The data for the Oracle request, represented as an `OracleRequest` object.
 * @returns {Promise<Mina.Transaction>} A promise that resolves to a Mina transaction containing the Oracle request.
 */
export async function buildOracleRequestTx(
  sender: Mina.FeePayerSpec,
  zkApp: SmartContract & IOracleClient,
  oracleRequest: OracleRequest
): Promise<Mina.Transaction<false,false>> {
  const offChainBytes = oracleRequest.toBinary(); // Convert request data to binary
  const reqField = Encoding.bytesToFields(offChainBytes); // Convert binary to fields
 
  return Mina.transaction(sender, async () => {
    await zkApp.sendOracleRequest(reqField[0], reqField[1], reqField[2], reqField[3]);
  });
}
 
/**
 * Builds a transfer and call transaction.
 *
 * @param {Mina.FeePayerSpec} sender - The sender of the transaction.
 * @param {SmartContract & IOracleClient} zkApp - The smart contract that implements the OracleClient interface.
 * @param {OracleRequest} oracleRequest - The oracle request to be sent.
 * @return {Promise<Mina.Transaction>} A promise that resolves to the built transaction.
 */
export async function buildTransferAndCallTx(
  sender: Mina.FeePayerSpec,
  pk: PublicKey,
  zkApp: SmartContract & IOracleClient,
  oracleRequest: OracleRequest
): Promise<Mina.Transaction<false,false>> {
  const offChainBytes = oracleRequest.toBinary(); // Convert request data to binary
  const reqField = Encoding.bytesToFields(offChainBytes); // Convert binary to fields
 
  return Mina.transaction(sender, async () => {
    AccountUpdate.fundNewAccount(pk);
    await zkApp.sendErc677RequestTo(
      reqField[0],
      reqField[1],
      reqField[2],
      reqField[3]
    );
  });
}
 
/**
 * A basic request client contract that implements the `IOracleClient` interface.
 */
export class BasicRequestClient extends SmartContract implements IOracleClient {
  /**
   * Represents an Oracle Address.
   *
   * @type {State<PublicKey>}
   */
  @state(PublicKey) oracleAddress = State<PublicKey>(); // State variable storing the Oracle's address
  /**
   * Represents the token address stored in the state.
   *
   * @type {State<PublicKey>}
   */
  @state(PublicKey) tokenAddress = State<PublicKey>(); // State variable storing the Token's address
  /**
   * Represents the initial state of a field in a data structure.
   *
   * @type {State<Field>}
   */
  @state(Field) data0 = State<Field>();
 
  /**
   * Initializes the instance.
   *
   * This method initializes the instance by calling the 'init' method of the super class, and
   * setting the value of 'this.data0' to 'Field(0)'.
   *
   * @returns {void}
   */
  init(): void {
    super.init();
    // this.oracleAddress.set(PublicKey.fromBase58(ORACLE_PUBLIC_KEY)); // Initialize with provided Oracle address
 
    this.data0.set(Field(0));
  }
 
  /**
   * Sets the stored Oracle contract address.
   *
   * @param {PublicKey} oracleAddress - The new Oracle contract address to set.
   * @returns {Bool} - A boolean indicating success (always true in this implementation).
   */
  @method async setOracleContract(oracleAddress: PublicKey) {
    this.oracleAddress.set(oracleAddress);
  }
 
  /**
   * Updates the stored ERC-677 token address associated with this client.
   *
   * @param {PublicKey} tokenAddress - The new PublicKey of the ERC-677 token.
   * @return {Bool} - True to indicate successful execution.
   */
  @method async setErc677Token(tokenAddress: PublicKey) {
    this.tokenAddress.set(tokenAddress);
  }
 
  /**
   * Sends an Oracle request to the stored Oracle contract.
   *
   * @param {PublicKey} oracleAddress - The new Oracle contract address to set.
   * @param {Field} req0 - The first field of the request data.
   * @param {Field} req1 - The second field of the request data.
   * @param {Field} req2 - The third field of the request data.
   * @param {Field} req3 - The fourth field of the request data.
   * @returns {Bool} - A boolean indicating success (determined by the Oracle contract).
   */
  @method async sendOracleRequestWithAddr(
    oracleAddress: PublicKey,
    req0: Field,
    req1: Field,
    req2: Field,
    req3: Field
  ) {
    // const oraclePublicKey = this.oraclePublicKey.get();
    // this.oraclePublicKey.assertEquals(oraclePublicKey);
 
    const oracleContract = new OracleContract(oracleAddress); // Instantiate Oracle contract
    await oracleContract.oracleRequest(req0, req1, req2, req3); // Forward request to Oracle
  }
 
  /**
   * Sends an Oracle request to the stored Oracle contract.
   *
   * @param {Field} req0 - The first field of the request data.
   * @param {Field} req1 - The second field of the request data.
   * @param {Field} req2 - The third field of the request data.
   * @param {Field} req3 - The fourth field of the request data.
   * @returns {Bool} - A boolean indicating success (determined by the Oracle contract).
   */
  @method async sendOracleRequest(
    req0: Field,
    req1: Field,
    req2: Field,
    req3: Field
  ) {
    const oraclePublicKey = this.oracleAddress.get();
    this.oracleAddress.requireEquals(this.oracleAddress.get());
 
    const oracleContract = new OracleContract(oraclePublicKey); // Instantiate Oracle contract
    await oracleContract.oracleRequest(req0, req1, req2, req3); // Forward request to Oracle
  }
 
  /**
   * Sends an ERC677 request to the Oracle contract.
   *
   * @param {Field} req0 - The first field of the request.
   * @param {Field} req1 - The second field of the request.
   * @param {Field} req2 - The third field of the request.
   * @param {Field} req3 - The fourth field of the request.
   *
   * @return {Bool} - Returns true if the request was successfully sent to the Oracle contract.
   */
  @method async sendErc677RequestTo(
    req0: Field,
    req1: Field,
    req2: Field,
    req3: Field
  ) {
    const tokenAddressPublicKey = this.tokenAddress.get();
    this.tokenAddress.requireEquals(this.tokenAddress.get());
 
    const oracleAddressPublicKey = this.oracleAddress.get();
    this.oracleAddress.requireEquals(this.oracleAddress.get());
 
    const tokenContract = new SErc677Contract(tokenAddressPublicKey);
    await tokenContract.transferAndCall(
      oracleAddressPublicKey,
      UInt64.from(100_000),
      req0,
      req1,
      req2,
      req3
    );
 
  }
 
  /**
   * Callback method for fulfilling an Oracle request.
   *
   * @param {Field} data0 - The data to fulfill the request with.
   * @returns {Bool} A boolean indicating success (always true in this implementation, potentially requiring verification).
   */
  @method async onFulfillRequest(data0: Field) {
    // verify from oracleContract
    this.data0.set(data0);
  }
}