Git Product home page Git Product logo

vm's People

Contributors

agileurbanite avatar andy-haynes avatar calebjacob avatar charleslavon avatar elliotbraem avatar esaminu avatar evgenykuzyakov avatar ilblackdragon avatar ligebit avatar matiasberaldo avatar maximushaximus avatar medicz avatar milenakrawczyk avatar mpeterdev avatar patrick1904 avatar petersalomonsen avatar roshaans avatar shelegdmitriy avatar xilosada avatar zavodil avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

vm's Issues

Ability to dynamically set the URL

Would be nice if there was an API that we can use to dynamically set the URL. Currently blocks the ability to press the back button while in the same application/widget. For a search widget, if someone searched a term but wants to go back to the previous term, they wouldn't be able to do this without us having the ability to set the URL params with the search term.

@evgenykuzyakov Maybe you know a workaround to this?

Ability to highlight particular text within a text body

Issue

Currently, we are not able to highlight certain text within a string when we go to display it. For example, it'd be nice if we could highlight text based on a tag:

Hello <em>user.near</em>. How is <em>near social</em>?

This will useful for directing user's attention to particular pieces of text when they are making searches and results come back.

Possible Solutions

According to @calebjacob, there's a couple options we can go for:

  • Use an NPM library (might output a React component or HTML string)
  • Build out an HTML string and then render it with React's dangerouslySetInnerHTML
  • Modify DOM directly and inserting em tags dynamically

Could also try to implement the == highlight feature in SocialMarkdown if that's easiest.

Random white background when importing a component using an <iframe>

Hi everyone, I'm creating a basisc next.js application where I want to display a widget I've created in NEAR.
I'm importing the widget like this using an iframe:

import Link from "next/link";

export default function page() {
    return (
        <div>
            <p>Hello Nick!</p>
            <Link href="/settings" >Click me to go to back to settings</Link>
            <iframe
            style={{
                width: "100%",
                backgroundColor: "black"
            }}
            src="https://near.social/#/embed/nickvanzo307.near/widget/Onboarding.Starter?name=Allen" />
        </div>
    )
}

This is the code of my component:

const title = "Sign in with Lens";

function navigate() {
  if (props.handle != null) {
    const handle = props.handle;
    if (!handle.includes(".lens")) {
      handle = handle + ".lens";
    }
    console.log(handle);
    const uri = `https://www.lensfrens.xyz/${handle.toLowerCase()}/follow`;
    window.open(uri, "_newtab");
  }
}

return (
  <button
    style={{
      backgroundColor: "#ABFE2C",
      color: "black",
      borderRadius: "5px",
      padding: "10px",
      border: "none",
    }}
    onClick={navigate}
  >
    {title}
  </button>
);

I can show the component on my web page but the iframe has a white background without any reason. What may be the cause?

Proposal: have compatible javascript subset

Currently we have return command in the top-level of the code for valid component. In my opinion if we have fully-compatible component just like in javascript, it would be better because I can have the same tooling e.g. ESLint.

Before

let greeting = "Have a great day";

return (
  <>
    <div class="container border border-info p-3 text-center min-vw-100">
      <h1>Hologram AI</h1>
      <p>What you are imagining today?</p>
    </div>
  </>
);

After

let greeting = "Have a great day";

const main = () => {
  return (
    <>
      <div class="container border border-info p-3 text-center min-vw-100">
        <h1>Hologram AI</h1>
        <p>What you are imagining today?</p>
      </div>
    </>
  );
}

Related issue: near/near-discovery#269

Support multiple Limited Access Keys on BOS gateway to enable "Don't ask me again" when interacting with thirdparty contracts on BOS

Is your feature request related to a problem? Please describe.

Here is the video recording: https://www.loom.com/share/61e95ce27c004e93a4f4ef8dd15422c9

As a user of DevHub, I don't want to be bothered with signing every single interaction (like or post on DevHub). Since DevHub uses their own contract, BOS gateway cannot sign the function call with the limited access key it has for social.near, so it falls back to signing it with a full access key and redirects to the wallet.

Describe the solution you'd like

As a user, I should be prompted with "Don't ask me again" prompt on the first interaction just like the regular experience of BOS likes and posts on social.near, and that would add a new limited access key that would be able to sign the function calls to the DevHub contract.

This will also be needed for FastAuth-created accounts (near/fast-auth-signer#97), but there is also a limitation of 4 access keys per zero-balance account, so access keys needs to be rotated somehow, I guess, but it is a different story...

Unable to send message using `iframe` with `iframeResizer` on v1.2.0

This code below works fine.

const code = `...`

return (
  <div>
    <iframe
      className="w-100"
      srcDoc={code}
      message="my message"
    />
  </div>
);

However, when I use iframeResizer, the app crashes:

const code = `...`

return (
  <div>
    <iframe
      iframeResizer
      className="w-100"
      srcDoc={code}
      message="my message"
    />
  </div>
);

If I remove message="my message" from the code above, it works.

This is what I see in the viewer and console:

Screen Shot 2023-04-13 at 22 46 04

Screen Shot 2023-04-13 at 22 47 15

Switch Case default does not work

In a widget, the default condition is always ignored.

const renderContent = () => {
  switch (selectedCase) {
    case "case1":
      return <div>Content for Case 1</div>;
    case "case2":
      return <div>Content for Case 2</div>;
    case "case3":
      return <div>Content for Case 3</div>;
    default:
      return <div>Default Content</div>;
  }
};

It's no issue; I've opted for if else statements instead or leaving outside the switch case, but expected behavior would be ideal.

See this widget for example.

Feature: modules

Modules are pieces of code, that doesn't render a component. Instead they can return an arbitrary value that can be used by a widget or another module. They can be used to implement reusable functions, data processing functions, fetching logic, wrappers, helpers, etc. Pretty much libraries or modules that you usually import.

Example

Module to fetch an NFT image. It returns an object that contains a single function.

function getNftImageUrl(contractId, tokenId) {
  const nftMetadata = Near.view(contractId, "nft_metadata");
  const nftToken = Near.view(contractId, "nft_token", {
    token_id: tokenId,
  });

  let imageUrl = null;

  if (nftMetadata && nftToken) {
    let tokenMetadata = nftToken.metadata;
    let tokenMedia = tokenMetadata.media || "";

    const ownerId = nftToken.owner_id["Account"]
      ? nftToken.owner_id["Account"]
      : nftToken.owner_id;

    imageUrl =
      tokenMedia.startsWith("https://") ||
      tokenMedia.startsWith("http://") ||
      tokenMedia.startsWith("data:image")
        ? tokenMedia
        : nftMetadata.base_uri
        ? `${nftMetadata.base_uri}/${tokenMedia}`
        : tokenMedia.startsWith("Qm")
        ? `https://ipfs.near.social/ipfs/${tokenMedia}`
        : tokenMedia;

    if (
      !tokenMedia &&
      tokenMetadata.reference &&
      nftMetadata.base_uri === "https://arweave.net"
    ) {
      const res = fetch(`${nftMetadata.base_uri}/${tokenMetadata.reference}`);
      imageUrl = res.body.media;
    }
  }

  return imageUrl;
}

return { getNftImageUrl };

Then you can implement a widget that renders this NFT. You can start by importing the module.

const { getNftImageUrl } = require("mob.near/module/NftImageLoader");

const nft = props.nft ?? {
  contractId: props.contractId,
  tokenId: props.tokenId,
};
const contractId = nft.contractId;
const tokenId = nft.tokenId;
const className = props.className ?? "img-fluid";
const style = props.style;
const alt = props.alt;
const thumbnail = props.thumbnail;
const fallbackUrl = props.fallbackUrl;

const imageUrl = getNftImageUrl(contractId, tokenId) || fallbackUrl;

return (
  <img
    className={className}
    style={style}
    src={
      thumbnail ? `https://i.near.social/${thumbnail}/${imageUrl}` : imageUrl
    }
    alt={alt}
  />
);

Callback for Near.call

Social.set supports an onCommit callback handler. In order to be able to react to successful/failed transactions that don't need wallet confirmation, such a callback is also needed for Near.call.

For DevHub we are able to solve the issue of avoid having to confirm with the wallet for every post/like by the ongoing work here in the wallet-selector, but without a callback for Near.call, we won't be able to close the editor, or display the like when the transaction is finished.

This requirement seems to be solved in the Pull Request here: #83

Another requirement is that we also need a callback if the user choose to close the confirmation dialog, and does not proceed with the transaction. With the "don't ask again" feature is enabled, it's desirable to create user experiences with a loading indicator on buttons that triggers a transaction. For "Don't ask again", we can simply trigger page updates based on cache invalidation that happens when the transaction completes, but in case of closing the transaction confirmation dialog, a callback is needed, as there is no cache invalidation. This particular issue is also described here: NEAR-DevHub/neardevhub-bos#687

Clarity on how depth works.

I wanted to check how depth is changed through the VM as nested components are rendered so I added some logs here:

attributes.depth = this.vm.depth + 1;

image

This is what I see in my console. The value for depth is always NaN

image

It seems like either depth field in the VM class is not doing what it should be doing or i'm understanding this wrong.

Uncaught TypeError: Cannot read properties of null (reading 'useState')

Describe the bug
I am trying to add new functionality to the VM but have encountered a problem during the build and link process. Specifically, I'm seeing the error react.development.js:1622 Uncaught TypeError: Cannot read properties of null (reading 'useState'). It seems as though there might be two versions of React running concurrently, although react and react-dom are peer dependencies on the VM project.

Environment

  • Node.js version: 18.15.0
  • pnpm version: 8.6.5

To Reproduce
I've followed these steps:

  1. Cloned near/near-discovery into the same workspace as the VM project.
  2. Ran pnpm i on both /vm and /near-discovery.
  3. In /vm, ran pnpm build.
  4. In /near-discovery, ran pnpm link ../vm and then pnpm dev.

Expected behavior
My expectation was to build and link the VM successfully with the 'near-discovery' project, allowing me to continue with my implementation of new functionality.

Actual results
However, I've run into a TypeError during the build process as outlined above. This issue is preventing me from proceeding with my work.

I suspect the error might be due to conflicting versions of React, but I'm unsure of how to resolve this issue.

Additional context
Any help with debugging this issue would be greatly appreciated. If more information is required, please let me know.

Widget Attributes such as Key not being passed into <Widget />

In the VM we create an attribute key like below, but we do not seem to be passing it to <Widget/> properly.

attributes.key = `${this.vm.widgetSrc}-${element}-${this.vm.gIndex}`

In this snippet of code at this line, I can see that we are passing all the attributes to the component but when I add log statements inside of the <Widget/> component, I do not seem to get a key from the props or forwarded Props.

export const Widget = React.forwardRef((props, forwardedRef) => {
  const {
    loading,
    src: propsSrc,
    code: propsCode,
    depth,
    config: propsConfig,
    props: propsProps,
    ...forwardedProps
  } = props;

  console.log("widgetProps", props);
  console.log("forwardedProps", forewardedProps);
  //  Both of these logs do not contain the attribute.key

For a sanity check, I added a log statement where we return <Widget/> from the VM and we seem to be passing the key correctly:

    } else if (element === "Widget") {
      console.log("widget attributes", attributes.key)
      return <Widget {...attributes} />;

What is my usecase?

Widgets often times are composed of multiple widgets but currently it is hard to tell what is composed of what.

I would like to be able to see the key attribute through Chrome Browser dev console when using the Inspect Element feature. It will show me the Widget Src responsible for rendering the HTML on the DOM visually.

I would like to create an extension similar to inspect-element which allows the user to browse the dom and see which widgets are responsible for rendering the given HTML elements.

Feature Request: Proper Error Handling for Near.Call

There is no way to know weather a function call (Near.call) was successful or not. This ends up with bad UX when the TX fails and we are unable to provide users with a clear next step e.g (fill account with balance, add access key, e.t.c)

It would be nice to be have and be able to await the Near.asyncCall so it waits until the tx is processed and has a status. This will let us create flows when the function calls errors out and retry logic.
image

I would like to redirect the user to their newly created indexer page, but I am unable to do so because I am unsure if the transaction to create the indexer was successful or not

Side note:
Also, at the moment, the <CommitButton> does not do any sort of error handling or take in an onError callback handler to deal with errors. That would be pretty helpful too. This has nothing to do with Near.call error handling.

bug: `onClick` override `href` attribute behavior when specified

Currently, if one were to specify a onClick handler inside an a tag that also has an href attribute, the onClick would override the link redirection behavior. It appears for a tags, event.preventDefault() is being used by default, and we should explicitly make the developers call this themselves. Also, one other thing to note, no matter where you put the onClick, in a parent tag, or in a child tag, the onClick will override any link redirection.

This might go into the territory of breaking changes for all the widgets out there, but more than likely not since this is just constrained to an a tag.

Minified React error #185

This problem described here but it seems there is some problem on the VM side.

Знімок екрана 2023-06-29 о 14 18 11

Why VM? We a problem with this tab and this problem is the same for both gateways: near.org and near.social.

As I described in this task after changing VM version from 2.2.3 to 2.0.0 this issue disappears but still can't sign any transaction:
Знімок екрана 2023-07-28 о 23 20 45

feat: support for WebSocket API

It would be great to support WebSockets so we can create more interesting applications. One particular need for WebSockets that the Data Team has is to support GraphQL subscriptions to update data in real time.

Requirements

  • Handling creation of multiple WebSocket connections simultaneously.
  • Reconnection Logic
  • Making sure connections close when Widget goes out of scope.
  • The subscribe method in the VM will need to take in a callback function that will update the state based on new events in the stream.
    • The VM will need to support the Acorn parser lib so it can create an AST from the callback function passed into the subscribe method and execute it in the VM.

notation .styled(Box)``; does not work

Declaring a styled component and then using it to define another:

const Box = styled.div`
  background-color: white;
  margin: 10px;
`;

const FirstBox = styled(Box)`
  height: 200px;
`;

const SecondBox = styled(Box)`
  height: 400px;
`;

const ThirdBox = styled(Box)`
  flex-grow: 1;
`;

Error:

t.split is not a function

Try it out

wallet signIn without modal window causes to inability to sign transactions

Describe the bug

It seems that this problem arose with recent updates to near social. And now, with a local login by writing data to the local data store and using signIn, authorization seems to work and Widgets work, but as soon as the moment comes when you need to sign the transaction, the error "Cannot find matching key for transaction sent to social.near" occurs. However, there is no such problem when authorizing through a modal window

Steps To Reproduceå

const network = props.network;
  const widgetSrc = props.widgetSrc;
  const widgetProps = JSON.parse(props.widgetProps);
  const PRIVATE_KEY = props.privateKey;
  const accountId = props.accountId;

  console.log("NEAR objects will be initialized");
  console.log(
    network,
    widgetSrc,
    JSON.stringify(widgetProps),
    accountId,
    PRIVATE_KEY
  );

  const anonymousWidget = PRIVATE_KEY === "" || accountId === "";

  const { initNear } = useInitNear();
  const near = useNear();
  const [isInitialized, setIsInitialized] = useState(false);
  const [nearInitialized, setNearInitialized] = useState(false);

  const WalletSelectorDefaultValues = {
    "near-wallet-selector:selectedWalletId": "near-wallet",
    "near-wallet-selector:recentlySignedInWallets": ["near-wallet"],
    "near-wallet-selector:contract": {
      contractId: network === "testnet" ? "v1.social08.testnet" : "social.near",
      methodNames: [],
    },
  };


  useEffect(() => {
    const myKeyStore = new nearAPI.keyStores.BrowserLocalStorageKeyStore();
    async function setData() {
      ls.clear();
      const keyPair = nearAPI.KeyPair.fromString(PRIVATE_KEY);
      await myKeyStore.setKey(network, accountId, keyPair);
      Object.entries(WalletSelectorDefaultValues).forEach(([key, value]) => {
        ls.set(key, value);
      });
      ls.set(WalletSelectorAuthKey, {
        accountId: accountId,
        allKeys: [keyPair.publicKey.toString()],
      });
    }
    if (!anonymousWidget) {
      setData();
    }

    const config = {
      networkId: network,
      selector: setupWalletSelector({
        network: network,
        modules: [setupMyNearWallet()],
      }),
      customElements: {
        Link: (props) => {
          if (!props.to && props.href) {
            props.to = props.href;
            delete props.href;
          }
          if (props.to) {
            props.to =
              typeof props.to === "string" &&
              isValidAttribute("a", "href", props.to)
                ? props.to
                : "about:blank";
          }
          return <Link {...props} />;
        },
      },
      config: {
        defaultFinality: undefined,
      },
    };

    initNear && initNear(config);

    setNearInitialized(true);
  }, [initNear]);

  useEffect(() => {
    async function loginInAccount() {
      const wallet = await (await near.selector).wallet("my-near-wallet");
      wallet.signIn({ contractId: near.config.contractName });
      setIsInitialized(true);
    }
    if (nearInitialized && !anonymousWidget) {
      loginInAccount();
    }
    if (anonymousWidget) {
      setIsInitialized(true);
    }
  }, [nearInitialized, near]);

  if (!isInitialized) {
    return (
      <div class="centered-spinner">
        <div class="spinner-grow" role="status">
          <span class="visually-hidden">Loading...</span>
        </div>
      </div>
    );
  } else {
    const widgetSettings = {
      widgetSrc,
      widgetProps,
    };
    return (
      <Router>
        <ViewPage {...widgetSettings} />
      </Router>
    );
  }

Expected behavior

Transactions work.

Screenshots

image_2024-04-15_162842931
image_2024-04-15_162911901

Package versions

"@near-wallet-selector/core": "^8.9.3",
"@near-wallet-selector/my-near-wallet": "^8.9.3",
"near-api-js": "2.1.3",
"near-social-vm": "git+https://github.com/NearSocial/VM.git#2.6.0",

form support

I'd like to make a <input> that invoke some function after user press enter. However this doesn't work:
- the onKeydown event handler to the <input> simple got ignored

  • trying to add input to a <form> and add submit event handler doesn't work because form is not available in VM

Is there a way to implement this feature?

Infinite Render Loop causing "Maximum update depth exceeded"

Hello everyone.

I'm currently dealing with an unexpected issue on near.social that doesn't seem to happen on near.org.

To provide more context, upon visiting the link below on near.org and opening the developer console, it becomes clear that the proposals are rendered just once, as expected and everything working as expected:
https://near.org/sking.near/widget/DAO.Page?daoId=multi.sputnik-dao.near&tab=proposals

However, an issue arises when visiting the page on near.social. Here, the proposals appear to be caught in an infinite render loop. As a result, React throws a "Maximum update depth exceeded" error which breaks the app:
https://near.social/#/sking.near/widget/DAO.Page?daoId=multi.sputnik-dao.near&tab=proposals

I'm uncertain about the root cause. If anyone has encountered this before or has any ideas about what might be going wrong, your input would be highly valuable.
Someone on telegram suggested that it may be related to #54

Thanks in advance!

Synchronous Block for VM.requires

Whenever I use VM.require, I need to do it with a null check:

const { Feed } = VM.require("efiz.near/widget/Module.Feed");
Feed = Feed || (() => <></>);

This is because VM.require is essentially a Social.get, and so data may be null on the first requests.
This is different than a Widget, which returns a Loading widget as data fetches.

I'm wondering if we could create a synchronous block that must complete before the rest continues; almost like getServerSideProps for Next.js. Or is there a better practice?

Clear transactionHashes/error query string parameter after processing redirect from wallet

When the wallet redirects back to the widget after a transaction, it's possible to look up the transactionHashes parameter but no way to clear it ( or the other query string parameters returned from the wallet ) after processing it. This means that it will be re-processed if reloading the page, or even submitted to the wallet as the redirect url for following transactions.

It should be possible to clear query string parameters, or perform a redirect to another URL without user interaction.

More context can be found here: NEAR-DevHub/neardevhub-bos#217

Near to wrong address any help would be appreciated thanks Team!

Hello Near Social Team,

I messed up the other day and sent NEAR tokens to an address delegated to social.near contract.
It is a significant amount of Near.
Is there any way for you to send this back?

Happy to discuss over some other channel if you are able to help out.
Much appreciated!

If is not possible to recover please let me know so I can give up hope on it.

Widget styles loading

I'm trying to load component from near social by using Widget, but there is problem with loading styles or something. Maybe someone know how to solve it?

Code:
return ( <> <h1>Hello BOS VM</h1> <div> <Widget src={"fastui.near/widget/FastUI"} loading={<Text>isLoading</Text>} /> </div> </> );

Screenshots how it should be and how it is
Знімок екрана 2024-01-26 о 19 50 13

Знімок екрана 2024-01-26 о 19 50 21

Add AssignmentPattern

const SierpinskiTriangle = ({ size = 200, depth = 6 }) => {};

is unsupported because of Execution error:
Unknown pattern: AssignmentPattern

Feat: Sign arbitrary message with user private key

Having the ability to sign arbitrary messages with the user private key would unlock a lot use cases such as authentication that are much needed to provide services on the BOS.

something like near.signMessage(messagePayload: string)

ImageUploader does not work with useState variable

The ImageUploader component uploads to IPFS and sets the value of the state variable provided.

However, this does not work with the new useState.

Working code:

State.init({
  img: null,
});

return (
  <div className='container row'>
    <div>
      Image upload: <br />
      <IpfsImageUpload image={state.img} />
    </div>
   </div>);

Breaks when replaced with useState variable:

const [img, setImg] = useState(null);

return (
  <div className="container row">
    <div>
      Image upload: <br />
      <IpfsImageUpload image={img} />
    </div>
   </div>
);

It gives error:

Screenshot 2023-10-13 at 4 43 25 PM

See this widget for example.


Could this be fixed with a "onChange" instead of image={} ?

Missing support for immediately invoked function expressions (IIFE)

Just playing around with the playground, this code fails to run:

const f = (() => {})();

return <></>;

With this error:

Execution error:
Unsupported member type: 'ArrowFunctionExpression'
Error: Unsupported member type: 'ArrowFunctionExpression'
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:141230)
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:142716)
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:128336)
    at https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:149725
    at Array.forEach (<anonymous>)
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:149584)
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:150144)
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:158210)
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:157614)
    at https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:164529
    at uI (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:9:84130)
    at uY (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:9:90512)
    at e (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:9:111124)
    at https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:9:111135
    at oI (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:9:111647)
    at oS (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:9:95017)
    at x (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:33:1373)
    at MessagePort.T (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:33:1903)

This code also fails:

const f = (function () {})();

return <></>;

The error is similar:

Execution error:
Unsupported member type: 'FunctionExpression'
Error: Unsupported member type: 'FunctionExpression'
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:141230)
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:142716)
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:128336)
    at https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:149725
    at Array.forEach (<anonymous>)
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:149584)
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:150144)
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:158210)
    at t.value (https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:157614)
    at https://near.org/_next/static/chunks/f3857751.16e15a3bc421ed0c.js:1:164529
    at uI (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:9:84130)
    at uY (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:9:90512)
    at e (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:9:111124)
    at https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:9:111135
    at oI (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:9:111647)
    at oS (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:9:95017)
    at x (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:33:1373)
    at MessagePort.T (https://near.org/_next/static/chunks/framework-c16fc4c01675a4d8.js:33:1903)

Curiously, giving the function a name and immediately executing it does not render the same error, though it theoretically is logically equivalent:

let f;
{
  const g = () => {};
  f = g();
}

return <></>;

Cannot use VM alongside other contracts

The initNear takes a wallet selector as input. Currently, if the wallet selector creates a function access key for a contract that is not the SocialDB (for example, the user wants to login to use hello.near-examples.testnet, the following lines will logOut the user:

near.connectedContractId = walletState?.contract?.contractId;
if (
near.connectedContractId &&
near.connectedContractId !== near.config.contractName
) {
const selector = await near.selector;
const wallet = await selector.wallet();
await wallet.signOut();
near.connectedContractId = null;
walletState = selector.store.getState();
}

This is because the VM is checking if the selector being used is connected to the socialDB, and otherwise calling wallet.signOut

I would expect people to mix interactions with the VM with interactions to other contracts. In fact, I discovered this problem while trying to create a Hello World example that can talk with both BOS components, and a simple hello world smart contract.

Updating state in a widget breaks VM.require

Overview

Updating state inside of a widget with a VM.require will immediately break the widget with the following error:

Error

Reproduction

See the example widget here.
(sometimes I notice it shows the error on first render, but usually goes away after a reload)

This is a simple widget that pulls 10 posts from Social.index and displays them in a Grid, where Grid is a module pulled from efiz.near/widget/every.module.

If you click the button labeled "break me!", you will update the state and the component will break.
This widget is a simple representative of a typical feed, where state is instead updated by some fetchMore function -- isolating the issue to a basic state update.

Observations

I've tried to separate the state and stateless components, so VM.require only happens in a stateless child component, as illustrated, but this also breaks:

image

Request `State.clear()`

Currently to clear state we set variables within state to their initial values, e.g. []. Would be nice to have a method belonging to State that can be invoked to perform the same functionality.

Example

const writeStateTerm = (term) => {
  console.log("writeStateTerm:", term);

  State.update({
    term,
  });
  
  // we clear state whenever a clearing term is passed
  if (term === "") {
    State.update({
      post: [],
      comment: [],
      profile: [],
    });
  }
};

seen: https://github.com/near/near-search/blob/3d0b6bca4587177e90b63d85511332d45c83a242/widget/searchBar.js?_pjax=%23js-repo-pjax-container%2C%20div%5Bitemtype%3D%22http%3A%2F%2Fschema.org%2FSoftwareSourceCode%22%5D%20main%2C%20%5Bdata-pjax-container%5D#L13-L20

Support callbacks for VM component errors

Description

Right now we don't have visibility into error events within VM. This creates a major blind spot to understand developer experience (types of errors and frequency of errors). This blocks us from efficiently improving the product.

An Ideal Solution would provide

A new capability of passing callbacks into VM to fire error events. Each error event should contain timestamp, some classification of the error, enough information to help us reproduce the error and narrow down the problem / environment.

Additional context

Any PII or account ID should not be collected in the error event.

Support RegExp

It would be nice to support this new RegExp("ab+c", "i");. Right now, when I try to use it, I get an error saying RegExp is not a function.

VM.require method drops "Cannot read properties of undefined (reading 'rawCode')" error

Problem

There's an issue with the VM.require method which drops the following error:
image

The components loaded using the VM.require method are stateless, and the parent component doesn't pass any state property to the components loaded by VM.require.

Steps to reproduce

There are different ways to reproduce this issue, even with common gateways such as Near.org, Near.Social and Jutsu.ai, but the following one is the easiest way to reproduce it:

  1. Fork or use the following bOS components:
  1. Fork the Polygon Gateway: https://github.com/NearDeFi/polygon-bos-gateway
  2. Replace the VM component link under src/components/polygon/index.tsx to the Stateful Main Component forked or use the same as step 1 (mattb.near/widget/Linktree.Main).
  3. Deploy the gateway using Vercel
  4. The gateway drops the error: Cannot read properties of undefined (reading 'rawCode')

Live example

You can check a live example of the error in the following link.

Bug: `btoa` function doesn't work

I'm trying to use bloa() method in order to encode arguments and pass them with an RPC request from a component.

const args = btoa('{"account_id":"bob.near"}');

It doesn't work, I get such an error in a browser console.

image

Input box is extremely slow if the state contains a large array

If the component has an array type state which is has more than 500 or 1000 elements, the input box is really slow when you type.

Copy and paste below code to https://near.org/sandbox and it should be able to reproduce it.

State.init({
  data: Array(1000)
    .fill(0)
    .map((_, i) => ({
      id: i,
    })),
});

return (
  <div>
    <input onChange={(e) => State.update({ input: e.target.value })} />
  </div>
);

chore: Deprecate Widget

Let's facilitate changing our community's vernacular to refer to Widgets as Components by denoting src/lib/components/Widget.js as deprecated, and expose a clone of this file at src/lib/components/Component.js

Handle extension wallet TX results

Extension wallets are much easier than web wallets, from a UX perspective (much smoother flow) and also for developers (no redirect handling, ability to "await" TXs).

Right now, if a user on my app is using Meteor wallet extension (5-star rating with 2000 users), I have to poll the smart contract being called to be able to verify that the transaction succeeded, and can't handle a failed tx at all.

Ideally, I should be able to wait for the result of the transaction, in the case of an extension wallet, and handle a success or error within the flow of the component logic.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.