Skip to content

Commit

Permalink
Merge pull request #47 from NearSocial/dev
Browse files Browse the repository at this point in the history
## 1.3.0

- Support `ethers.js` based on NearSocial/viewer#130
  - Expose `Ethers` and `ethers` in the global scope.
  - Add custom `Web3Connect` component that renders Web3 connect/disconnect button. Currently, the API is heavily influenced by Web3Onboard API.
  - VM now exports `EthersProviderContext` React context type. A gateway that wants to support Ethers.js should wrap the app with `EthersProviderContext.Provider` component with the object value `{provider}`. Provider is Web3 provider that can be used to create an Ethers.js provider.
- Fix `initNear` logic to assign provided `config` values on top of the default values, instead of reverse.
- Update `near-api-js` dependency to ^2.1.0
- Fix `elliptic` library by doing a lazy `deepClone` when it's first requested a VM instance.
- Update VM to reflect `0.10.0` SocialDB changes. NearSocial/social-db#8
  - Assume the permission to write is granted by default when `set` is called on the current account.
  - Use `get_account_storage` to account for the shared storage.
  • Loading branch information
Evgeny Kuzyakov authored Apr 24, 2023
2 parents 1006452 + cb9394b commit 9983512
Show file tree
Hide file tree
Showing 13 changed files with 691 additions and 52 deletions.
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Changelog

## 1.3.0

- Support `ethers.js` based on https://github.com/NearSocial/viewer/pull/130
- Expose `Ethers` and `ethers` in the global scope.
- Add custom `Web3Connect` component that renders Web3 connect/disconnect button. Currently, the API is heavily influenced by Web3Onboard API.
- VM now exports `EthersProviderContext` React context type. A gateway that wants to support Ethers.js should wrap the app with `EthersProviderContext.Provider` component with the object value `{provider}`. Provider is Web3 provider that can be used to create an Ethers.js provider.
- Fix `initNear` logic to assign provided `config` values on top of the default values, instead of reverse.
- Update `near-api-js` dependency to ^2.1.0
- Fix `elliptic` library by doing a lazy `deepClone` when it's first requested a VM instance.
- Update VM to reflect `0.10.0` SocialDB changes. https://github.com/NearSocial/social-db/pull/8
- Assume the permission to write is granted by default when `set` is called on the current account.
- Use `get_account_storage` to account for the shared storage.

## 1.2.0

- Added support for using [Iframe Resizer](https://github.com/davidjbradshaw/iframe-resizer) for rendering responsive iframes. This library automatically resizes the iframe to match the child content size to avoid scrollbars on the iframe itself. You can use the library by adding an `iframeResizer` prop to an `<iframe>` tag:
Expand Down
2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "near-social-vm",
"version": "1.2.0",
"version": "1.3.0",
"description": "Near Social VM",
"main": "dist/index.js",
"files": [
Expand Down Expand Up @@ -44,12 +44,14 @@
"collections": "^5.1.12",
"deep-equal": "^2.2.0",
"elliptic": "^6.5.4",
"ethers": "^5.7.2",
"idb": "^7.1.1",
"iframe-resizer-react": "^1.1.0",
"local-storage": "^2.0.0",
"lodash": "^4.17.21",
"mdast-util-find-and-replace": "^2.0.0",
"nanoid": "^4.0.1",
"near-api-js": "^0.45.1",
"near-api-js": "^2.1.0",
"prettier": "^2.7.1",
"react-bootstrap": "^2.5.0",
"react-bootstrap-typeahead": "^6.0.0",
Expand Down
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Widget } from "./lib/components/Widget";
import { useCache } from "./lib/data/cache";
import * as utils from "./lib/data/utils";
import { CommitButton } from "./lib/components/Commit";
import { EthersProviderContext } from "./lib/components/ethers";

export {
Widget,
Expand All @@ -15,4 +16,5 @@ export {
useAccount,
useAccountId,
utils,
EthersProviderContext,
};
5 changes: 5 additions & 0 deletions src/lib/components/Widget.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, {
useCallback,
useContext,
useEffect,
useLayoutEffect,
useState,
Expand All @@ -25,6 +26,7 @@ import { useAccountId } from "../data/account";
import Big from "big.js";
import uuid from "react-uuid";
import { isFunction } from "react-bootstrap-typeahead/types/utils";
import { EthersProviderContext } from "./ethers";

const AcornOptions = {
ecmaVersion: 13,
Expand Down Expand Up @@ -85,6 +87,7 @@ export const Widget = React.forwardRef((props, forwardedRef) => {
const [prevVmInput, setPrevVmInput] = useState(null);
const [configs, setConfigs] = useState(null);
const [srcOrCode, setSrcOrCode] = useState(null);
const ethersProviderContext = useContext(EthersProviderContext);

const cache = useCache();
const near = useNear();
Expand Down Expand Up @@ -210,6 +213,7 @@ export const Widget = React.forwardRef((props, forwardedRef) => {
requestCommit,
version: uuid(),
widgetConfigs: configs,
ethersProviderContext,
});
setVm(vm);
return () => {
Expand All @@ -223,6 +227,7 @@ export const Widget = React.forwardRef((props, forwardedRef) => {
requestCommit,
confirmTransactions,
configs,
ethersProviderContext,
]);

useEffect(() => {
Expand Down
27 changes: 27 additions & 0 deletions src/lib/components/ethers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import React, { useContext } from "react";

export const EthersProviderContext = React.createContext(null);

export const Web3ConnectButton = (props) => {
const ethersProviderContext = useContext(EthersProviderContext);
const [{ wallet, connecting }, connect, disconnect] =
ethersProviderContext?.useConnectWallet
? ethersProviderContext?.useConnectWallet()
: [{}];

return (
<button
className={`btn ${props.className} ${
connecting || wallet ? "btn-outline-secondary" : "btn-outline-primary"
}`}
disabled={(wallet ? !disconnect : !connect) || connecting}
onClick={() => (wallet ? disconnect?.(wallet) : connect?.())}
>
{connecting
? props.connectingLabel ?? "Connecting"
: wallet
? props.disconnectLabel ?? "Disconnect Web3 Wallet"
: props.connectLabel ?? "Connect Web3 Wallet"}
</button>
);
};
1 change: 1 addition & 0 deletions src/lib/data/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ const loadAccount = async (near, setAccount) => {
const signedAccountId = near.accountId;
if (signedAccountId) {
ls.set(LsKeyAccountId, signedAccountId);
near.config.walletConnectCallback(signedAccountId);
} else {
ls.remove(LsKeyAccountId);
}
Expand Down
16 changes: 16 additions & 0 deletions src/lib/data/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const Action = {
Block: "Block",
LocalStorage: "LocalStorage",
CustomPromise: "CustomPromise",
EthersCall: "EthersCall",
};

const CacheStatus = {
Expand Down Expand Up @@ -386,6 +387,21 @@ class Cache {
this.invalidateCallbacks(cached, false);
}
}

cachedEthersCall(ethersProvider, callee, args, invalidate) {
if (!ethersProvider) {
return null;
}
return this.cachedPromise(
{
action: Action.EthersCall,
callee,
args,
},
() => ethersProvider[callee](...args),
invalidate
);
}
}

const defaultCache = new Cache();
Expand Down
23 changes: 9 additions & 14 deletions src/lib/data/commitData.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,23 +33,18 @@ export const prepareCommit = async (
alert("You're not logged in. Sign in to commit data.");
return;
}
const [storageBalance, permissionGranted] = await Promise.all([
near.viewCall(near.config.contractName, "storage_balance_of", {
const [accountStorage, permissionGranted] = await Promise.all([
near.viewCall(near.config.contractName, "get_account_storage", {
account_id: signedAccountId,
}),
signedAccountId !== accountId
? near.viewCall(near.config.contractName, "is_write_permission_granted", {
predecessor_id: signedAccountId,
key: accountId,
})
: near.publicKey
? near.viewCall(near.config.contractName, "is_write_permission_granted", {
public_key: near.publicKey.toString(),
key: accountId,
})
: Promise.resolve(false),
: Promise.resolve(true),
]);
const availableStorage = Big(storageBalance?.available || "0");
const availableBytes = Big(accountStorage?.available_bytes || "0");
let data = {
[accountId]: convertToStringLeaves(originalData),
};
Expand All @@ -61,18 +56,18 @@ export const prepareCommit = async (
const expectedDataBalance = StorageCostPerByte.mul(
estimateDataSize(data, currentData)
)
.add(storageBalance ? Big(0) : InitialAccountStorageBalance)
.add(accountStorage ? Big(0) : InitialAccountStorageBalance)
.add(permissionGranted ? Big(0) : StorageForPermission)
.add(ExtraStorageBalance);
const deposit = bigMax(
expectedDataBalance.sub(availableStorage),
permissionGranted ? Big(0) : storageBalance ? Big(1) : MinStorageBalance
expectedDataBalance.sub(availableBytes.mul(StorageCostPerByte)),
permissionGranted ? Big(0) : accountStorage ? Big(1) : MinStorageBalance
);
return {
originalData,
accountId,
storageBalance,
availableStorage,
accountStorage,
availableBytes,
currentData,
data,
expectedDataBalance,
Expand Down
14 changes: 10 additions & 4 deletions src/lib/data/near.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,13 @@ async function web4ViewCall(contractId, methodName, args, fallback) {
}
}

async function _initNear({ networkId, config, keyStore, selector } = {}) {
async function _initNear({
networkId,
config,
keyStore,
selector,
walletConnectCallback = () => {},
}) {
if (!config) {
config = {};
if (!networkId) {
Expand All @@ -213,13 +219,13 @@ async function _initNear({ networkId, config, keyStore, selector } = {}) {
config.networkId = networkId;
}
if (config.networkId === "mainnet") {
config = Object.assign({}, config, MainNearConfig);
config = Object.assign({}, MainNearConfig, config);
} else if (config.networkId === "testnet") {
config = Object.assign({}, config, TestNearConfig);
config = Object.assign({}, TestNearConfig, config);
}
config.walletConnectCallback = walletConnectCallback;
keyStore = keyStore ?? new nearAPI.keyStores.BrowserLocalStorageKeyStore();


const nearConnection = await nearAPI.connect(
Object.assign({ deps: { keyStore } }, config)
);
Expand Down
6 changes: 5 additions & 1 deletion src/lib/data/utils.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import Big from "big.js";
import React from "react";
import equal from "deep-equal";
import { ethers } from "ethers";

export const TGas = Big(10).pow(12);
export const MaxGasPerTransaction = TGas.mul(250);
Expand Down Expand Up @@ -336,6 +337,7 @@ function isGetter(obj, prop) {
}

export const deepFreeze = (obj) => {
Object.freeze(obj);
Object.keys(obj).forEach((prop) => {
if (
!isGetter(obj, prop) &&
Expand All @@ -345,7 +347,7 @@ export const deepFreeze = (obj) => {
deepFreeze(obj[prop]);
}
});
return Object.freeze(obj);
return obj;
};

export const ReactKey = "$$typeof";
Expand All @@ -371,6 +373,8 @@ export const deepCopy = (o) => {
return new Blob([o], { type: o.type });
} else if (o instanceof Uint8Array || o instanceof ArrayBuffer) {
return o.slice(0);
} else if (o instanceof ethers.BigNumber) {
return o;
} else if (isObject(o)) {
if (isReactObject(o)) {
return o;
Expand Down
Loading

0 comments on commit 9983512

Please sign in to comment.