Open Michaelsulistio opened 1 week ago
Thank you for this comprehensive issue report!
In React Native applications, when trying to use
@coral-xyz/anchor
>=v0.29.0
Why is it specifically >= 0.29.0
? The library has been using Buffer
pretty much since the beginning, so this issue should exist on all versions.
- Locally patch the
Buffer.subarray
function
Not pretty but at least it's a short fix. Is there a published polyfill that does this?
2. Patch
@coral-xyz/anchor
to useslice
instead ofsubarray
Not an ideal because
subarray
should be more performant thanslice
.
Not only that but also slice
method is deprecated afaik.
Buffer
compatibility has not only been an issue for React Native, but also browsers too. The best solution long term would be to completely get rid of it, but unfortunately, we still depend on packages that use it internally.
Why is it specifically >= 0.29.0? The library has been using Buffer pretty much since the beginning, so this issue should exist on all versions.
The issue lies with the usage of subarray
in decodeUnchecked
, not just with Buffer
. This is the commit that introduced subarray
into decodeUnchecked
.
So whichever version of the package includes that commit, is when it started becoming problematic for React Native. On second glance, seems like that commit began inclusion in some version of v0.28.X?
Let me know what is the starting version that includes that commit, and I can update the issue title for more accurate documentation.
Not pretty but at least it's a short fix. Is there a published polyfill that does this?
Not that I know of, most discussion online just encourages the project to manually polyfill. The @craftzdog/react-native-buffer
package actually includes this polyfill into their implementation of Buffer
but it wouldn't help in this case, because acc: Buffer
is produced by @solana/web3.js
which itself uses the problematic buffer
package.
The best solution long term would be to completely get rid of it, but unfortunately, we still depend on packages that use it internally.
Yup, like mentioned above, this issue comes all the way from the Connection
class from @solana/web3.js
which itself depends on buffer
.
For an interim solution, this issue/behavior should be properly documented and the fix I mentioned should be discoverable. Is there anywhere on the Anchor documentation we can add some warning/disclaimer for React Native behavior?
Describe the bug
In React Native applications, when trying to use
@coral-xyz/anchor
>=v0.29.0
, users will run into this error when using the library to fetch and decode certain accounts (i.e inprogram.account.accountName.fetch()
):Other expected
Buffer
methods likereadUInt32LE
will fail too (have not tested myself).Specifically, in my case, the stack trace is throwing an error in
buffer-layout
'sUInt
layout classdecode
method.Root issue
The root of the issue stems from this
subarray
function call indecodeUnchecked
.The returned
data
is aUint8Array
when it should be aBuffer
. This means it is missing the functionreadUIntLE
and this causes the error later inbuffer-layout
'sdecode
method.Explanation
acc
is aBuffer
that comes from@solana/web3,js
which uses thebuffer
npm package.In React Native runtime environment (Hermes)
Buffer.subarray
behaves differently than on Browser/Node environment. This is a known issue(1, 2). As a result, thesubarray
call incorrectly returns an instance of aUint8Array
rather than aBuffer
.For a full understanding, read this issue.
Solution
1. Locally patch the
Buffer.subarray
functionWe can manually fix the
subarray
function by patching theBuffer.subarray
prototype to explicitly return an object that has the expectedBuffer
methods (likereadUIntLE
).In
polyfills.ts
:2. Patch
@coral-xyz/anchor
to useslice
instead ofsubarray
Not an ideal because
subarray
should be more performant thanslice
.