Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add wrappers to easily convert between ScVal and native types. #630

Merged
merged 22 commits into from
Jun 26, 2023

Conversation

Shaptic
Copy link
Contributor

@Shaptic Shaptic commented Jun 22, 2023

This adds the following new helper functions:

export function nativeToScVal(x: any): xdr.ScVal;
export function scValToNative(scv: xdr.ScVal): any;

Related: #628.

The possible conversions are outlined in the docstring.
The test case should outline a thorough usage example.

From native types to xdr.ScVal

  /**
   * The conversions are as follows:
   *
   *  - xdr.ScVal -> passthrough
   *  - null/undefined -> scvVoid
   *  - string -> scvString (a copy is made)
   *  - UintArray8/Buffer -> scvBytes (a copy is made)
   *  - boolean -> scvBool
   *
   *  - number/bigint -> the smallest possible integer type that will fit the
   *    input value; if you want a specific type, you should use {@link ScInt}
   *    and either pass a `type` option or call the appropriate `.to<size>()`
   *    conversion helper.
   *
   *  - {@link Address} -> scvAddress (for contracts and public keys)
   *
   *  - Array<T> -> scvVec after attempting to convert each item of type `T` to
   *    an xdr.ScVal (recursively). note that all values must be the same type!
   *
   *  - object -> scvMap after attempting to convert each key and value to an
   *    xdr.ScVal (recursively). note that there is no restriction on types
   *    matching anywhere (unlike arrays)
   **/

From xdr.ScVal to a native type.

  /**
   * Possible conversions include:
   *
   *  - void -> null
   *  - u32, i32 -> number
   *  - u64, i64, u128, i128, u256, i256 -> bigint
   *  - vec -> array of any of the above (via recursion)
   *  - map -> key-value object of any of the above (via recursion)
   *  - bool -> boolean
   *  - bytes -> Uint8Array
   *  - string, symbol -> string
   **/

Demo

let input = {
    bool: true,
    void: null,
    u32: xdr.ScVal.scvU32(1),
    i32: xdr.ScVal.scvI32(1),
    u64: 1n,
    i64: -1n,
    u128: new ScInt(1).toU128(),
    i128: new ScInt(1).toI128(),
    u256: new ScInt(1).toU256(),
    i256: new ScInt(1).toI256(),
    map: {
        arbitrary: 1n,
        nested: 'values',
        etc: false
    },
    vec: ['same', 'type', 'list']
};

let expectedOutput = xdr.ScVal.scvMap([
    new xdr.ScMapEntry({
        key: xdr.ScVal.scvString('bool'),
        val: xdr.ScVal.scvBool(true),
    }),
    new xdr.ScMapEntry({
        key: xdr.ScVal.scvString('void'),
        val: xdr.ScVal.scvVoid(),
    }),
    new xdr.ScMapEntry({
        key: xdr.ScVal.scvString('u32'),
        val: xdr.ScVal.scvU32(1),
    }),
    new xdr.ScMapEntry({
        key: xdr.ScVal.scvString('i32'),
        val: xdr.ScVal.scvI32(1),
    }),
    new xdr.ScMapEntry({
        key: xdr.ScVal.scvString('u64'),
        val: xdr.ScVal.scvU64(new xdr.int64(1)),
    }),
    new xdr.ScMapEntry({
        key: xdr.ScVal.scvString('i64'),
        val: xdr.ScVal.scvI64(new xdr.nt64(-1)),
    }),
    new xdr.ScMapEntry({
        key: xdr.ScVal.scvString('u128'),
        val: new ScInt(1, { type: 'u128' }).toScVal(),
    }),
    new xdr.ScMapEntry({
        key: xdr.ScVal.scvString('i128'),
        val: new ScInt(1, { type: 'i128' }).toScVal(),
    }),
    new xdr.ScMapEntry({
        key: xdr.ScVal.scvString('u256'),
        val: new ScInt(1, { type: 'u256' }).toScVal(),
    }),
    new xdr.ScMapEntry({
        key: xdr.ScVal.scvString('i256'),
        val: new ScInt(1, { type: 'i256' }).toScVal(),
    }),
    new xdr.ScMapEntry({
        key: xdr.ScVal.scvString('map'),
        val: xdr.ScVal.scvMap([
            new xdr.ScMapEntry({
                key: xdr.ScVal.scvString('arbitrary'),
                val: xdr.ScVal.scvU64(new xdr.Uint64(1))
            }),
            new xdr.ScMapEntry({
                key: xdr.ScVal.scvString('nested'),
                val: xdr.ScVal.scvString('values')
            }),
            new xdr.ScMapEntry({
                key: xdr.ScVal.scvString('etc'),
                val: xdr.ScVal.scvBool(false)
            })
        ])
    }),
    new xdr.ScMapEntry({
        key: xdr.ScVal.scvString('vec'),
        val: xdr.ScVal.scvVec([
            xdr.ScVal.scvString('same'), 
            xdr.ScVal.scvString('type'), 
            xdr.ScVal.scvString('list'),
        ])
    }),
]);

nativeToScVal(input).toXDR() == expectedOutput.toXDR(); // true

@Shaptic Shaptic marked this pull request as ready for review June 22, 2023 21:25
@Shaptic Shaptic linked an issue Jun 22, 2023 that may be closed by this pull request
22 tasks
Copy link

@aristidesstaffieri aristidesstaffieri left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️ SmartParser, lgtm!

src/numbers/xdr_large_int.js Show resolved Hide resolved
src/smart.js Outdated Show resolved Hide resolved
@Shaptic Shaptic merged commit 016afc4 into soroban Jun 26, 2023
@Shaptic Shaptic deleted the scval-wrapper branch June 26, 2023 23:13
Shaptic added a commit that referenced this pull request Sep 12, 2023
* Correctly set `minAccountSequence` in `TransactionBuilder` for large values (#539)
* Add support of CAP40 ed25519SignedPayload signer for SetOptionOp (#542)
* Add TypeScript interfaces for Ed25519SignedPayload signers
* Coalesce all xLM, Xlm, etc. => 'XLM' native asset code (#546)
* make sure sodium is not an empty object in service workers (#567)
* Add futurenet passphrase for soroban. (#550)
* Include standalone network passphrase (#555)
* Soroban auth next updates (#570)
* Add strkey parsing for contracts, and Address helper for building ScAddresses (#572)
* Update xdr to include HashIdPreimageContractAuth.nonce (#577)
* Add Address.toBuffer method (#578)
* Soroban value overhaul (#582)
* Update generated XDR to latest version. (#587)
* Update XDR and contract invocations to conform to the latest version (Preview 9). (#601)
* added soroban transaction data as tx builder param (#604)
* Add Contract support for strkey-style contract IDs (#612)
* Add Contract.address() method (#614)
* Add wrappers to easily deal with the myriad of `ScVal` integer types. (#620)
* Upgrade `js-xdr` to v3.0.0 to support `bigint` encoding.
* Add wrappers to easily convert between `ScVal` and native types. (#630)
* Update XDR to support Preview 10 (#633)
* Fix TypeScript definition for `invokeHostFunction` options (#635)
* Add fully-qualified `Operation` type to XDR type definitions. (#591)
* Adds Operation.isValidAmount jsdoc (#609)
* Removes the dependency on `crc` by calculating checksum in strkey (#621)
* Improve type flexibility when building `ScVal`s from native types (#638)
* Fix Preview 10 contract invoke & release `v10.0.0-soroban.3` (#642)
* Add GitHub Action that compares before-and-after bundle sizes. (#644)
* Make opinionated judgements about string/symbol decoding (#645)
* Make Node 16 the minimum version. (#651)
* Add standalone/futurenet passphrases to jsdoc (#654)
* Clean up unnecessary dependency entries (#652)
* Add `SorobanDataBuilder` builder pattern to prepare transactions easier (#660)
* Adds a way to create a `TransactionBuilder` from an existing transaction. (#656)
* Add basic contract event parsing into a human-readable structure (#659)
* Drop support for deprecated hex contract IDs (#658)
* Add helpers method to build authorization entries. (#663)
* Fix TypeScript definition for new static `TransactionBuilder` constructor (#665)
* Add ability to clear out operations from the transaction builder (#670)
* Add an existing method to XdrLargeInt, jsdoc/types fixup (#668)
* Expand contract footprint with contract code ledger key. (#662)
* Decode base64-encoded strings in new SorobanDataBuilder (#673)
* Add ability to modify and retrieve the resource footprint (#680)
* Fixes error messages for required amount parameters (#679)
* Add `Asset.contractId()` helper to predict contract IDs (#684)
* Upgrade dependencies to their latest minor/patch version (#685)
* Improves `SorobanDataBuilder` construction and adds a getter (#686)
* Add JSON-ification of Soroban invocation trees. (#669)
* Add utilities for formatting token amounts (`formatTokenAmount` & `parseTokenAmount`) (#667)
* Merges the final Protocol 20 XDR (i.e. for testnet) into `soroban` (#688)
* Add support to convert strings to large integer and address `ScVal`s (#690)

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Paul Bellamy <[email protected]>
Co-authored-by: George <[email protected]>
Co-authored-by: Jun Luo <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: OrbitLens <[email protected]>
Co-authored-by: Piyal Basu <[email protected]>
Co-authored-by: George Kudrayvtsev <[email protected]>
Co-authored-by: shawn <[email protected]>
Co-authored-by: Silence <[email protected]>
Co-authored-by: Chad Ostrowski <[email protected]>
Co-authored-by: jeesun 지선 <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

Add abstractions for converting ScVals to native types.
3 participants