Skip to content

Commit

Permalink
Merge pull request #14 from script3/val-calldata-fix
Browse files Browse the repository at this point in the history
feat: add calldata conversions and clean up Val and Calldata
  • Loading branch information
mootz12 authored Jun 28, 2024
2 parents 092d60d + c8affc2 commit f339075
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 46 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.1.0",
"version": "1.2.0",
"name": "@script3/soroban-governor-sdk",
"description": "Javascript SDK for the Soroban Governor",
"type": "module",
Expand Down
61 changes: 61 additions & 0 deletions src/calldata_utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Address, nativeToScVal, xdr } from "@stellar/stellar-sdk";
import { Calldata, Val } from ".";

/**
* Convert Calldata "Vals" to ScVals. This is required for the calldata to be used in the smart contract.
* When using the Governor Client, this is done automatically.
*
* @param calldata
* @returns - The calldata with Vals converted to ScVals
*/
export function convertValsToScVals(calldata: Calldata): any {
return {
args: calldata.args.map((arg) => valToScVal(arg)),
auths: calldata.auths.map((auth) => convertValsToScVals(calldata)),
contract_id: new Address(calldata.contract_id),
function: calldata.function,
};
}

/**
* Convert a Val to an ScVal using nativeToScVal.
*
* If you have a complicated object that does not work with nativeToScVal, you
* can either supply a `xdr.ScVal` object directly and the type will be ignored, or,
* you can supply the ScVal as a Base64 XDR string and include `type: { type: "xdr" }` as
* Val's type, and it will be converted to an ScVal directly.
*
* @param val - The Val to convert to an ScVal
* @returns - The xdr ScVal object
*/
export function valToScVal(val: Val): xdr.ScVal {
if (val.type.type === "xdr") {
return xdr.ScVal.fromXDR(val.value, "base64");
}
return nativeToScVal(val.value, val.type);
}

/**
* Convert a Calldata object to a SorobanAuthorizedInvocation object.
* @param calldata - The calldata to convert
* @returns - The xdr SorobanAuthorizedInvocation object
*/
export function calldataToAuthInvocation(
calldata: Calldata
): xdr.SorobanAuthorizedInvocation {
let auth_function =
xdr.SorobanAuthorizedFunction.sorobanAuthorizedFunctionTypeContractFn(
new xdr.InvokeContractArgs({
contractAddress: new Address(calldata.contract_id).toScAddress(),
functionName: calldata.function,
args: calldata.args.map((arg) => valToScVal(arg)),
})
);
let subInvocations = calldata.auths.map((auth) =>
calldataToAuthInvocation(auth)
);
return new xdr.SorobanAuthorizedInvocation({
function: auth_function,
subInvocations: subInvocations,
});
}
92 changes: 49 additions & 43 deletions src/governor.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import {
Address,
Contract,
contract,
nativeToScVal,
xdr,
} from "@stellar/stellar-sdk";
import { Address, Contract, contract } from "@stellar/stellar-sdk";
import { Buffer } from "buffer";
import { convertValsToScVals } from "./calldata_utils.js";
import type { Option, i128, u32 } from "./index.js";

/**
Expand Down Expand Up @@ -95,54 +90,65 @@ export interface GovernorSettings {

/**
* This is a wrapper for the XDR type ScVal. It is used to convert between
* a string based representation of the value and the internal XDR type.
* a JS based representation of to the ScVal type used in Soroban.
*
* See the Stellar SDK's [nativeToScVal](https://stellar.github.io/js-stellar-sdk/ContractSpec.html#nativeToScVal) implementation
* for more information.
*
* @param value - The value to convert to an ScVal
* @param type - An object containing a type property that is the ScVal representation.
* @returns The ScVal representation of the value
*
* @example
* - i32 ScVal with value 10
* ```js
* {
* value: 10,
* type: {
* type: "i32"
* }
* }
* ```
*
* - Address ScVal with the zero address
* ```js
* {
* value: "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF",
* type: {
* type: "Address"
* }
* }
* ```
*
* - Complex ScVal encoded as XDR. (This is an example of `GovernorSettings` as an ScVal)
* ```js
* {
* value: "AAAAEQAAAAEAAAAIAAAADwAAAA1jb3VudGluZ190eXBlAAAAAAAAAwAAAAYAAAAPAAAADGdyYWNlX3BlcmlvZAAAAAMAAdiAAAAADwAAABJwcm9wb3NhbF90aHJlc2hvbGQAAAAAAAoAAAAAAAAAAAAAAAJUC+QAAAAADwAAAAZxdW9ydW0AAAAAAAMAAAH0AAAADwAAAAh0aW1lbG9jawAAAAMAAIcAAAAADwAAAAp2b3RlX2RlbGF5AAAAAAADAACHAAAAAA8AAAALdm90ZV9wZXJpb2QAAAAAAwAAyoAAAAAPAAAADnZvdGVfdGhyZXNob2xkAAAAAAADAAAT7A=="
* type: {
* type: "xdr"
* }
* }
* ```
*/
export class Val {
value: string;
export interface Val {
value: any;
type: any;

constructor(value: string, type: any) {
this.value = value;
this.type = type;
}

toScVal(): xdr.ScVal {
return nativeToScVal(this.value, this.type);
}
}

/**
* Object for storing call data
* Calldata for a proposal action. Defines a contract action the Governor will take
* when the proposal is executed.
*
* @param args - The arguments for the contract invocation
* @param auths - The authorizations required by the governor for the contract invocation
* @param contract_id - The contract ID of the contract to invoke
* @param function - The function to invoke on the contract
*/
export class Calldata {
export interface Calldata {
args: Array<Val>;
auths: Array<Calldata>;
contract_id: string;
function: string;

constructor(
contract_id: string,
function_: string,
args: Array<Val>,
auths: Array<Calldata>
) {
this.args = args;
this.auths = auths;
this.contract_id = contract_id;
this.function = function_;
}

convertValsToScVals(): any {
return {
args: this.args.map((arg) => arg.toScVal()),
auths: this.auths.map((auth) => auth.convertValsToScVals()),
contract_id: new Address(this.contract_id),
function: this.function,
};
}
}

/**
Expand Down Expand Up @@ -382,7 +388,7 @@ export class GovernorContract extends Contract {
action: ProposalAction;
}): string {
if (action.tag === "Calldata") {
let new_value = action.values[0].convertValsToScVals();
let new_value = convertValsToScVals(action.values[0]);
action = { tag: "Calldata", values: [new_value] };
}
return this.call(
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./calldata_utils.js";
export * from "./contract_error.js";
export * from "./contract_result.js";
export * from "./governor.js";
Expand Down

0 comments on commit f339075

Please sign in to comment.