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

[TypeError]: XDR Write Error: [object Object] is not a ScVal #1285

Closed
kalepail opened this issue Apr 17, 2024 · 26 comments · Fixed by #1314 or #1326
Closed

[TypeError]: XDR Write Error: [object Object] is not a ScVal #1285

kalepail opened this issue Apr 17, 2024 · 26 comments · Fixed by #1314 or #1326
Assignees
Labels
bug Something isn't working

Comments

@kalepail
Copy link
Contributor

What version are you using?

https://github.com/stellar/js-stellar-sdk/tree/cf-worker
(this is a fork of master with a custom axios adapter to work with Cloudflare Workers)

What did you do?

Tried to use the TS bindings to call a contract method.

What did you expect to see?

Success.

What did you see instead?

[TypeError]: XDR Write Error: [object Object] is not a ScVal

Extra info

Here's a simple repo showcasing the error
https://github.com/Colorglyph/colorglyph-viewer

@kalepail kalepail added the bug Something isn't working label Apr 17, 2024
@kalepail
Copy link
Contributor Author

Full unminified error

✘ [ERROR] a [TypeError]: XDR Write Error: [object Object] is not a ScVal

      at p.write
  (file:///Users/tylervanderhoeven/Desktop/Web/Colorglyph-2.0/colorglyph-viewer/node_modules/@stellar/js-xdr/dist/webpack:/XDR/src/union.js:85:13)
      at ve.write
  (file:///Users/tylervanderhoeven/Desktop/Web/Colorglyph-2.0/colorglyph-viewer/node_modules/@stellar/js-xdr/dist/webpack:/XDR/src/var-array.js:43:23)
      at p.write
  (file:///Users/tylervanderhoeven/Desktop/Web/Colorglyph-2.0/colorglyph-viewer/node_modules/@stellar/js-xdr/dist/webpack:/XDR/src/struct.js:31:12)
      at p.write
  (file:///Users/tylervanderhoeven/Desktop/Web/Colorglyph-2.0/colorglyph-viewer/node_modules/@stellar/js-xdr/dist/webpack:/XDR/src/union.js:88:21)
      at p.write
  (file:///Users/tylervanderhoeven/Desktop/Web/Colorglyph-2.0/colorglyph-viewer/node_modules/@stellar/js-xdr/dist/webpack:/XDR/src/struct.js:31:12)
      at p.write
  (file:///Users/tylervanderhoeven/Desktop/Web/Colorglyph-2.0/colorglyph-viewer/node_modules/@stellar/js-xdr/dist/webpack:/XDR/src/union.js:88:21)
      at p.write
  (file:///Users/tylervanderhoeven/Desktop/Web/Colorglyph-2.0/colorglyph-viewer/node_modules/@stellar/js-xdr/dist/webpack:/XDR/src/struct.js:31:12)
      at ve.write
  (file:///Users/tylervanderhoeven/Desktop/Web/Colorglyph-2.0/colorglyph-viewer/node_modules/@stellar/js-xdr/dist/webpack:/XDR/src/var-array.js:43:23)
      at p.write
  (file:///Users/tylervanderhoeven/Desktop/Web/Colorglyph-2.0/colorglyph-viewer/node_modules/@stellar/js-xdr/dist/webpack:/XDR/src/struct.js:31:12)
      at p.toXDR
  (file:///Users/tylervanderhoeven/Desktop/Web/Colorglyph-2.0/colorglyph-viewer/node_modules/@stellar/js-xdr/dist/webpack:/XDR/src/xdr-type.js:57:10)

@kalepail
Copy link
Contributor Author

My best guess is there's a mix between using or bundling a client side / browser version of something with a server / node version of something and that toggle is correct some or even most of the time but in the Cloudflare edge environment it isn't and thus there's some type mismatch.

@kalepail
Copy link
Contributor Author

I will say it's really strange to me that the stellar-sdk works while the TS bindings version, which uses the same stellar-sdk doesn't. That seems odd and possibly a good place to start poking around.

@BlaineHeffron
Copy link
Contributor

I've been looking into this bug as well. I'm pretty new to the Stellar ecosystem but I figured I'd post my current findings in case someone with more familiarity with the xdr library might have some insight. I found that simply putting the Hello World sample contract hello method in a front end <script> tag triggers it if you are using the soroban-astro-template (ie following this guide ).

It works fine when the hello method is put in the front matter of the Astro page, ie when its run server side. When run client side, the error occurs due to the if (!(value instanceof this)) in union.js. It looks like the element it is trying to write extends Enum instead of Union. Perhaps something with the client environment is different in the way the transaction object is being parsed into XDR?

@BlaineHeffron
Copy link
Contributor

BlaineHeffron commented May 7, 2024

Bug Reproduction Steps

  1. Run commands:
mkdir xdr-write-error && cd xdr-write-error 
soroban contract init . -w increment --frontend-template https://github.com/stellar/soroban-astro-template
cp .env.example .env
npm install
  1. Open src/pages/index.astro

  2. Locate the second --- line and add the following script just below it:

<script>
import helloWorld from "../contracts/hello_world";
const { result } = await helloWorld.hello({ to: "you" });
console.log(result);
</script>
  1. Run the following command:
npm run dev
  1. Navigate to http://localhost:4321/

@janewang
Copy link
Contributor

janewang commented May 7, 2024

Could be a sdk bug...

@janewang
Copy link
Contributor

janewang commented May 7, 2024

@Shaptic We are quite blocked on this. Would you be able to take a look in this or pair with @BlaineHeffron on this? Thanks in advance :)

@Shaptic
Copy link
Contributor

Shaptic commented May 7, 2024

There's likely a stellar-base somewhere that there shouldn't be, or an SDK version mismatch. Can you please give it another go with v12.0.0-rc2 to see if the issue persists?

@kalepail
Copy link
Contributor Author

kalepail commented May 7, 2024

Just tried here: Colorglyph/colorglyph-viewer@ad6ecab
No dice.
If @BlaineHeffron has a more basic repro though that's likely a better place to test as I'm also combining the event source one with an axios patch all to work on CF

@Shaptic
Copy link
Contributor

Shaptic commented May 7, 2024

The astro template has outdated dependencies which might be causing this, but I can't find a similar issue in colorglyph 😕

I wonder if, for some reason, exporting the SDK as part of the generated client somehow creates a copy that conflicts with the built-ins.... or if this is another instance of this bug and that bridge needs to be crossed now.

@kalepail
Copy link
Contributor Author

kalepail commented May 8, 2024

Updated the astro site with all the latest stuff
https://github.com/kalepail/xdr-write-error

You have to spin up a local docker network before running npm run dev.
Make sure you're running the latest p21 docker image.

docker run --rm -i \
    -p "8000:8000" \
    --name stellar \
    stellar/quickstart:testing \
    --local \
    --limits unlimited \
    --enable-soroban-rpc \
    --enable-soroban-diagnostic-events \
    --enable rpc,horizon

@kalepail
Copy link
Contributor Author

kalepail commented May 8, 2024

I'm also using the latest CLI version right from the main branch.
cargo install --git https://github.com/stellar/soroban-cli soroban-cli --features opt which currently is this commit 9bc48fd

@kalepail
Copy link
Contributor Author

kalepail commented May 8, 2024

Another instance of this bug stellar/js-soroban-client#124

@kalepail
Copy link
Contributor Author

kalepail commented May 8, 2024

@chadoh did we confirm this was fixed in the 12rc2? My tests indicated it did not

@Shaptic
Copy link
Contributor

Shaptic commented May 8, 2024

Probably an auto-close via GitHub, I'll reopen

@Shaptic Shaptic reopened this May 8, 2024
@chadoh
Copy link
Contributor

chadoh commented May 8, 2024

I think GitHub did that because I have this in the description:

Known limitations

Still haven't fixed #1285

@Shaptic
Copy link
Contributor

Shaptic commented May 8, 2024

me github, me description.find("fixed #") != -1, me close issue

@Shaptic
Copy link
Contributor

Shaptic commented May 9, 2024

I've opened stellar/js-xdr#122 as an attempt to patch this due to its urgency and our (my) inability to root cause this quickly, please give it a look!

@BlaineHeffron
Copy link
Contributor

@Shaptic It still fails the new check. Uncaught TypeError: XDR Write Error: [object Object] is r2, not ScVal Apparently it is in the same spot as before (Union.js, checking the hello payload).

@BlaineHeffron
Copy link
Contributor

Some more info, the JSON stringify value of what fails is {"_switch":{"name":"scvSymbol","value":15},"_arm":"sym","_armType":{"_maxLength":32},"_value":"you"}

The prototype is as follows for server build:

{
  constructor: class extends Union {},
  scvBool: function set(value) {
          return this.set(aSwitch, value);
        },
  scvVoid: function set(value) {
          return this.set(aSwitch, value);
        },
  scvError: function set(value) {
          return this.set(aSwitch, value);
        },
  scvU32: function set(value) {
          return this.set(aSwitch, value);
        },
  scvI32: function set(value) {
          return this.set(aSwitch, value);
        },
  scvU64: function set(value) {
          return this.set(aSwitch, value);
        },
  scvI64: function set(value) {
          return this.set(aSwitch, value);
        },
  scvTimepoint: function set(value) {
          return this.set(aSwitch, value);
        },
  scvDuration: function set(value) {
          return this.set(aSwitch, value);
        },
  scvU128: function set(value) {
          return this.set(aSwitch, value);
        },
  scvI128: function set(value) {
          return this.set(aSwitch, value);
        },
  scvU256: function set(value) {
          return this.set(aSwitch, value);
        },
  scvI256: function set(value) {
          return this.set(aSwitch, value);
        },
  scvBytes: function set(value) {
          return this.set(aSwitch, value);
        },
  scvString: function set(value) {
          return this.set(aSwitch, value);
        },
  scvSymbol: function set(value) {
          return this.set(aSwitch, value);
        },
  scvVec: function set(value) {
          return this.set(aSwitch, value);
        },
  scvMap: function set(value) {
          return this.set(aSwitch, value);
        },
  scvAddress: function set(value) {
          return this.set(aSwitch, value);
        },
  scvContractInstance: function set(value) {
          return this.set(aSwitch, value);
        },
  scvLedgerKeyContractInstance: function set(value) {
          return this.set(aSwitch, value);
        },
  scvLedgerKeyNonce: function set(value) {
          return this.set(aSwitch, value);
        },
  b: function get() {
            return this.get(armsName);
          },
  error: function get() {
            return this.get(armsName);
          },
  u32: function get() {
            return this.get(armsName);
          },
  i32: function get() {
            return this.get(armsName);
          },
  u64: function get() {
            return this.get(armsName);
          },
  i64: function get() {
            return this.get(armsName);
          },
  timepoint: function get() {
            return this.get(armsName);
          },
  duration: function get() {
            return this.get(armsName);
          },
  u128: function get() {
            return this.get(armsName);
          },
  i128: function get() {
            return this.get(armsName);
          },
  u256: function get() {
            return this.get(armsName);
          },
  i256: function get() {
            return this.get(armsName);
          },
  bytes: function get() {
            return this.get(armsName);
          },
  str: function get() {
            return this.get(armsName);
          },
  sym: function get() {
            return this.get(armsName);
          },
  vec: function get() {
            return this.get(armsName);
          },
  map: function get() {
            return this.get(armsName);
          },
  address: function get() {
            return this.get(armsName);
          },
  nonceKey: function get() {
            return this.get(armsName);
          },
  instance: function get() {
            return this.get(armsName);
          },
}

The client version (webpack build) prototype

{
  constructor: class extends X {
                },
  scvBool: function(t6) {
                      return this.set(e6, t6);
                    },
  scvVoid: function(t6) {
                      return this.set(e6, t6);
                    },
  scvError: function(t6) {
                      return this.set(e6, t6);
                    },
  scvU32: function(t6) {
                      return this.set(e6, t6);
                    },
  scvI32: function(t6) {
                      return this.set(e6, t6);
                    },
  scvU64: function(t6) {
                      return this.set(e6, t6);
                    },
  scvI64: function(t6) {
                      return this.set(e6, t6);
                    },
  scvTimepoint: function(t6) {
                      return this.set(e6, t6);
                    },
  scvDuration: function(t6) {
                      return this.set(e6, t6);
                    },
  scvU128: function(t6) {
                      return this.set(e6, t6);
                    },
  scvI128: function(t6) {
                      return this.set(e6, t6);
                    },
  scvU256: function(t6) {
                      return this.set(e6, t6);
                    },
  scvI256: function(t6) {
                      return this.set(e6, t6);
                    },
  scvBytes: function(t6) {
                      return this.set(e6, t6);
                    },
  scvString: function(t6) {
                      return this.set(e6, t6);
                    },
  scvSymbol: function(t6) {
                      return this.set(e6, t6);
                    },
  scvVec: function(t6) {
                      return this.set(e6, t6);
                    },
  scvMap: function(t6) {
                      return this.set(e6, t6);
                    },
  scvAddress: function(t6) {
                      return this.set(e6, t6);
                    },
  scvContractInstance: function(t6) {
                      return this.set(e6, t6);
                    },
  scvLedgerKeyContractInstance: function(t6) {
                      return this.set(e6, t6);
                    },
  scvLedgerKeyNonce: function(t6) {
                      return this.set(e6, t6);
                    },
  b: function() {
                      return this.get(t6);
                    },
  error: function() {
                      return this.get(t6);
                    },
  u32: function() {
                      return this.get(t6);
                    },
  i32: function() {
                      return this.get(t6);
                    },
  u64: function() {
                      return this.get(t6);
                    },
  i64: function() {
                      return this.get(t6);
                    },
  timepoint: function() {
                      return this.get(t6);
                    },
  duration: function() {
                      return this.get(t6);
                    },
  u128: function() {
                      return this.get(t6);
                    },
  i128: function() {
                      return this.get(t6);
                    },
  u256: function() {
                      return this.get(t6);
                    },
  i256: function() {
                      return this.get(t6);
                    },
  bytes: function() {
                      return this.get(t6);
                    },
  str: function() {
                      return this.get(t6);
                    },
  sym: function() {
                      return this.get(t6);
                    },
  vec: function() {
                      return this.get(t6);
                    },
  map: function() {
                      return this.get(t6);
                    },
  address: function() {
                      return this.get(t6);
                    },
  nonceKey: function() {
                      return this.get(t6);
                    },
  instance: function() {
                      return this.get(t6);
                    },
}

Note that X is Enum

These are from my notes so they aren't from your PR on js-xdr.

@BlaineHeffron
Copy link
Contributor

BlaineHeffron commented May 9, 2024

I also checked the logic around line 150 of union.js. I printed out statements regarding which class it decided on for the children. These were identical in both builds. I ultimately determined the problem isn't within js-xdr because I used the server build of js-xdr and the error still occurred.

@Shaptic
Copy link
Contributor

Shaptic commented May 9, 2024

Great notes, thank you 🙏

I think if we can figure out where the heck r2 is coming from (in the error message, which is the constructor name of the value getting passed to Union::write), we might make progress 🕵️

@BlaineHeffron
Copy link
Contributor

Here is the json stringify and prototype with the new js-xdr code:

value is {"_switch":{"name":"scvSymbol","value":15},"_arm":"sym","_armType":{"_maxLength":32},"_value":"you"} union.js:95:14
prototype is {
  constructor: class extends $ {
                },
  scvBool: function(t6) {
                      return this.set(e6, t6);
                    },
  scvVoid: function(t6) {
                      return this.set(e6, t6);
                    },
  scvError: function(t6) {
                      return this.set(e6, t6);
                    },
  scvU32: function(t6) {
                      return this.set(e6, t6);
                    },
  scvI32: function(t6) {
                      return this.set(e6, t6);
                    },
  scvU64: function(t6) {
                      return this.set(e6, t6);
                    },
  scvI64: function(t6) {
                      return this.set(e6, t6);
                    },
  scvTimepoint: function(t6) {
                      return this.set(e6, t6);
                    },
  scvDuration: function(t6) {
                      return this.set(e6, t6);
                    },
  scvU128: function(t6) {
                      return this.set(e6, t6);
                    },
  scvI128: function(t6) {
                      return this.set(e6, t6);
                    },
  scvU256: function(t6) {
                      return this.set(e6, t6);
                    },
  scvI256: function(t6) {
                      return this.set(e6, t6);
                    },
  scvBytes: function(t6) {
                      return this.set(e6, t6);
                    },
  scvString: function(t6) {
                      return this.set(e6, t6);
                    },
  scvSymbol: function(t6) {
                      return this.set(e6, t6);
                    },
  scvVec: function(t6) {
                      return this.set(e6, t6);
                    },
  scvMap: function(t6) {
                      return this.set(e6, t6);
                    },
  scvAddress: function(t6) {
                      return this.set(e6, t6);
                    },
  scvContractInstance: function(t6) {
                      return this.set(e6, t6);
                    },
  scvLedgerKeyContractInstance: function(t6) {
                      return this.set(e6, t6);
                    },
  scvLedgerKeyNonce: function(t6) {
                      return this.set(e6, t6);
                    },
  b: function() {
                      return this.get(t6);
                    },
  error: function() {
                      return this.get(t6);
                    },
  u32: function() {
                      return this.get(t6);
                    },
  i32: function() {
                      return this.get(t6);
                    },
  u64: function() {
                      return this.get(t6);
                    },
  i64: function() {
                      return this.get(t6);
                    },
  timepoint: function() {
                      return this.get(t6);
                    },
  duration: function() {
                      return this.get(t6);
                    },
  u128: function() {
                      return this.get(t6);
                    },
  i128: function() {
                      return this.get(t6);
                    },
  u256: function() {
                      return this.get(t6);
                    },
  i256: function() {
                      return this.get(t6);
                    },
  bytes: function() {
                      return this.get(t6);
                    },
  str: function() {
                      return this.get(t6);
                    },
  sym: function() {
                      return this.get(t6);
                    },
  vec: function() {
                      return this.get(t6);
                    },
  map: function() {
                      return this.get(t6);
                    },
  address: function() {
                      return this.get(t6);
                    },
  nonceKey: function() {
                      return this.get(t6);
                    },
  instance: function() {
                      return this.get(t6);
                    },
} union.js:96:14
Uncaught TypeError: XDR Write Error: [object Object] is r2, not ScVal
    n errors.js:3
    write union.js:97
    write var-array.js:43
    write struct.js:31
    write union.js:103
    write struct.js:31
    write union.js:103
    write struct.js:31
    write var-array.js:43
    write struct.js:31
    toXDR xdr-type.js:57
    toXDR xdr-type.js:12
    toEnvelope transaction.js:303
    toXDR transaction_base.js:244
    _callee13$ server.js:416
    tryCatch server.js:24
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:34771
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:34711
    asyncGeneratorStep server.js:25
    _next server.js:26
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:34954
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:34946
    _simulateTransaction server.js:429
    _callee12$ server.js:396
    tryCatch server.js:24
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:34771
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:34711
    asyncGeneratorStep server.js:25
    _next server.js:26
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:34954
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:34946
    simulateTransaction server.js:404
    _callee$ assembled_transaction.js:61
    tryCatch assembled_transaction.js:33
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:48129
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:48069
    asyncGeneratorStep assembled_transaction.js:34
    _next assembled_transaction.js:35
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:48312
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:48304
    _callee7$ assembled_transaction.js:440
    tryCatch assembled_transaction.js:33
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:48129
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:48069
    asyncGeneratorStep assembled_transaction.js:34
    _next assembled_transaction.js:35
    promise callback*asyncGeneratorStep assembled_transaction.js:34
    _next assembled_transaction.js:35
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:48312
    node_modules @stellar_stellar-sdk_lib_contract_client_index__js.js:48304
    build assembled_transaction.js:450
    assembleTransaction2 client.js:39
    <anonymous> index.astro:11
errors.js:3:4

@BlaineHeffron
Copy link
Contributor

I printed out the prototypes in var-array, union, and struct and everything is identical to the server build up until that scvSymbol.

This is very odd, in the old build I could trace the symbol back to it being a child of Enum. But in this case the $ is stumping me. So I added some debug text in the Enum class, and it seems to be called 'k' in this build. So either I was mistaken before and it wasn't a child of Enum or something in some changes caused its inheritance to change...

@janewang
Copy link
Contributor

Fixes stellar/js-stellar-sdk#962

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Status: Done
5 participants