Skip to content

Commit

Permalink
PKG - [sdk] Implement GetNetworkParameters (#1420)
Browse files Browse the repository at this point in the history
* Add getNetwork util

* Implement GetNetworkParameters interaction
  • Loading branch information
Huy Nguyen authored Dec 6, 2022
1 parent 00a5cb0 commit c20bc34
Show file tree
Hide file tree
Showing 35 changed files with 361 additions and 29 deletions.
9 changes: 9 additions & 0 deletions .changeset/gold-cougars-run.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@onflow/fcl": minor
"@onflow/sdk": minor
"@onflow/transport-grpc": minor
"@onflow/transport-http": minor
"@onflow/fcl-wc": patch
---

Add GetNetworkParameters interaction and a util to get chain ID
19 changes: 17 additions & 2 deletions packages/fcl-wc/src/fcl-wc.test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
import * as fclWC from "./fcl-wc"
import {config} from "@onflow/config"

describe("Init Client", () => {
it("should throw without projectId", async () => {
async function testFn() {

// Mock transport then import fcl-wc because startup of fcl will call getChainId util which hits the chain
await config.overload(
{
"flow.network.default": "testnet",
"sdk.transport": async ix => ix
},
async () => {
const fclWC = require("./fcl-wc")
await fclWC.init()
}
)
}

expect.assertions(1)
await expect(fclWC.init()).rejects.toThrow(Error)
await expect(testFn).rejects.toThrow(Error)
})
})
4 changes: 2 additions & 2 deletions packages/fcl-wc/src/utils.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {log, LEVELS} from "@onflow/util-logger"
import {config} from "@onflow/config"
import {invariant} from "@onflow/util-invariant"
import * as fcl from "@onflow/fcl"

export let CONFIGURED_NETWORK = null

export const setConfiguredNetwork = async () => {
CONFIGURED_NETWORK = await config.get("flow.network")
CONFIGURED_NETWORK = await fcl.getChainId()
invariant(
CONFIGURED_NETWORK,
"FCL Configuration value for 'flow.network' is required"
Expand Down
10 changes: 9 additions & 1 deletion packages/fcl/TRANSITIONS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,12 @@

When specifying which flow network for FCL to use, use the `flow.network` config key instead of `env` (e.g. `fcl.config.put("flow.network", "testnet")`). Permitted values are currently `local`, `canarynet`, `testnet`, `mainnet`.

FCL currently falls back to `env` for the `flow.network` field but this will be removed in a future update.
FCL currently falls back to `env` for the `flow.network` field but this will be removed in a future update.

## 0002 Deprecate `flow.network` config key
- **Date:** September 26th 2022
- **Type:** Deprecation of `flow.network` in config

FCL now has a built-in utility to get which flow network to use. Manual specification in config is no longer required

FCL currently falls back to `flow.network` in case of failure but this will be removed in a future update.
19 changes: 4 additions & 15 deletions packages/fcl/src/app-utils/verify-signatures.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import {config} from "@onflow/config"
import {log} from "@onflow/util-logger"
import {invariant} from "@onflow/util-invariant"
import {withPrefix, sansPrefix} from "@onflow/util-address"
import {query} from "../exec/query"
import {encodeAccountProof} from "../wallet-utils"
import {isString} from "../exec/utils/is"
import {getChainId} from "../utils"

const ACCOUNT_PROOF = "ACCOUNT_PROOF"
const USER_SIGNATURE = "USER_SIGNATURE"
Expand Down Expand Up @@ -54,25 +53,15 @@ export const validateArgs = args => {
}
}

// TODO: pass in option for contract but we're connected to testnet
// log address + network -> in sync?
const getVerifySignaturesScript = async (sig, opts) => {
const verifyFunction =
sig === "ACCOUNT_PROOF"
? "verifyAccountProofSignatures"
: "verifyUserSignatures"

let network = await config.get("flow.network")
if (!network) {
network = await config.get("env")
if (network)
log.deprecate({
pkg: "FCL",
subject:
'Using the "env" configuration key for specifying the flow network',
message: 'Please use "flow.network" instead.',
transition:
"https://github.com/onflow/flow-js-sdk/blob/master/packages/fcl/TRANSITIONS.md#0001-deprecate-env-config-key",
})
}
let network = await getChainId()

let fclCryptoContract

Expand Down
4 changes: 3 additions & 1 deletion packages/fcl/src/current-user/exec-service/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {invariant} from "@onflow/util-invariant"
import {log, LEVELS} from "@onflow/util-logger"
import {serviceRegistry} from "./plugins"
import {configLens} from "../../default-config"
import {getChainId} from "../../utils"
import {VERSION} from "../../VERSION"
import {configLens} from "../../default-config"

const execStrategy = async ({service, body, config, opts}) => {
const strategy = serviceRegistry.getStrategy(service.method)
Expand All @@ -19,6 +20,7 @@ export async function execService({service, msg = {}, config = {}, opts = {}}) {
fclVersion: VERSION,
fclLibrary: "https://github.com/onflow/fcl-js",
hostname: window?.location?.hostname ?? null,
network: await getChainId(),
},
}

Expand Down
5 changes: 5 additions & 0 deletions packages/fcl/src/default-config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {config} from "@onflow/config"
import {setChainIdDefault} from "./utils/getChainId"

const isServerSide = () => typeof window === "undefined"

Expand All @@ -13,6 +14,10 @@ config({
"fcl.storage.default": SESSION_STORAGE,
})

// this is an async function but we can't await bc it's run at top level.
// NOT guaranteed that flow.network.default is set after this call (or at startup)
setChainIdDefault()

export async function configLens(regex) {
return Object.fromEntries(
Object.entries(await config().where(regex)).map(([key, value]) => [
Expand Down
2 changes: 2 additions & 0 deletions packages/fcl/src/discovery/services.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {config} from "@onflow/config"
import {invariant} from "@onflow/util-invariant"
import {serviceRegistry} from "../current-user/exec-service/plugins"
import {getChainId} from "../utils"
import {VERSION} from "../VERSION"
import {makeDiscoveryServices} from "./utils"

Expand All @@ -26,6 +27,7 @@ export async function getServices({types}) {
clientServices: await makeDiscoveryServices(),
supportedStrategies: serviceRegistry.getStrategies(),
userAgent: window?.navigator?.userAgent,
network: await getChainId(),
}),
}).then(d => d.json())
}
1 change: 1 addition & 0 deletions packages/fcl/src/discovery/services.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ describe("getServices", () => {
"discovery.authn.endpoint",
"https://fcl-discovery.onflow.org/api/testnet/authn"
)
.put("accessNode.api", "https://rest-testnet.onflow.org")
})

afterEach(() => {
Expand Down
4 changes: 2 additions & 2 deletions packages/fcl/src/exec/utils/derive-dependencies.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {config} from "@onflow/config"
import {invariant} from "@onflow/util-invariant"
import {withPrefix} from "@onflow/util-address"
import {getChainId} from "../../utils"

export async function deriveDependencies({template}) {
const network = await config.get("flow.network")
const network = await getChainId()

invariant(
network,
Expand Down
4 changes: 2 additions & 2 deletions packages/fcl/src/exec/utils/prep-template-opts.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import * as sdk from "@onflow/sdk"
import {retrieve} from "../../document/document.js"
import {normalizeInteractionTemplate} from "../../normalizers/interaction-template/interaction-template"
import {deriveCadenceByNetwork} from "../../interaction-template-utils/derive-cadence-by-network.js"
import {deriveDependencies} from "./derive-dependencies"
import {isString} from "./is"
import {getChainId} from "../../utils"

export async function prepTemplateOpts(opts) {
if (isString(opts?.template)) {
Expand All @@ -20,7 +20,7 @@ export async function prepTemplateOpts(opts) {
opts.cadence ||
deriveCadenceByNetwork({
template: opts.template,
network: await sdk.config().get("flow.network"),
network: await getChainId(),
})

opts.cadence = cadence
Expand Down
3 changes: 3 additions & 0 deletions packages/fcl/src/fcl.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ export {AppUtils}
import * as InteractionTemplateUtils from "./interaction-template-utils"
export {InteractionTemplateUtils}

export {getChainId} from "./utils"

export {TestUtils} from "@onflow/sdk"
export {config} from "@onflow/config"
export {send} from "@onflow/sdk"
Expand Down Expand Up @@ -66,6 +68,7 @@ export {getBlockHeader} from "@onflow/sdk"
export {getCollection} from "@onflow/sdk"
export {getTransactionStatus} from "@onflow/sdk"
export {getTransaction} from "@onflow/sdk"
export {getNetworkParameters} from "@onflow/sdk"
export {authorizations, authorization} from "@onflow/sdk"
export {args, arg} from "@onflow/sdk"
export {proposer} from "@onflow/sdk"
Expand Down
1 change: 1 addition & 0 deletions packages/fcl/src/fcl.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
payer,
ref,
createSignableVoucher,
config,
} from "@onflow/sdk"
import {VERSION} from "@onflow/sdk/src/VERSION"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {log, LEVELS} from "@onflow/util-logger"
import {query} from "../exec/query.js"
import {generateTemplateId} from "./generate-template-id.js"
import {normalizeInteractionTemplate} from "../normalizers/interaction-template/interaction-template.js"
import {getChainId} from "../utils"

export async function getInteractionTemplateAudits(
{template, auditors},
Expand Down Expand Up @@ -52,7 +53,7 @@ export async function getInteractionTemplateAudits(

let FlowInteractionAuditContract = opts.flowInteractionAuditContract
if (!FlowInteractionAuditContract) {
const fclNetwork = await config().get("flow.network")
const fclNetwork = await getChainId()
invariant(
fclNetwork === "mainnet" || fclNetwork === "testnet",
"getInteractionTemplateAudits Error: Unable to determine address for FlowInteractionTemplateAudit contract. Set configuration for 'fcl.network' to 'mainnet' or 'testnet'"
Expand Down
58 changes: 58 additions & 0 deletions packages/fcl/src/utils/getChainId.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import * as sdk from "@onflow/sdk"
import {config} from "@onflow/config"
import {log} from "@onflow/util-logger"
import { invariant } from "@onflow/util-invariant"

async function getChainIdFromAccessNode() {
const response = await sdk.send([sdk.getNetworkParameters()]).then(sdk.decode)
return response.chainId
}

export async function setChainIdDefault() {
const network = await getChainIdFromAccessNode()
config.put("flow.network.default", network)
return network
}

export async function getChainId() {
let network = await config.get("flow.network.default")

if (!network) {
network = await setChainIdDefault()

if (!network) {
network = await config.get("flow.network")

if (network) {
log.deprecate({
pkg: "FCL",
subject:
'Using the "flow.network" configuration key for specifying the flow network',
message: "Configuring flow.network is no longer required",
transition:
"https://github.com/onflow/flow-js-sdk/blob/master/packages/fcl/TRANSITIONS.md#0002-deprecate-flow.network-config-key",
})
} else {
network = await config.get("env")

if (network)
log.deprecate({
pkg: "FCL",
subject:
'Using the "env" configuration key for specifying the flow network',
message:
"Configuring to specify flow network is no longer required",
transition:
"https://github.com/onflow/flow-js-sdk/blob/master/packages/fcl/TRANSITIONS.md#0001-deprecate-env-config-key",
})
}
}
}

invariant(
network,
"Error getting chainId from access node. Please configure flow.network instead"
)

return network
}
15 changes: 15 additions & 0 deletions packages/fcl/src/utils/getChainId.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {config} from "@onflow/config"
import assert from "assert"
import {getChainId} from "./getChainId"

describe("getChainId", () => {
it("getChainId assuming it's already in config", async () => {
let network

await config.overload({"flow.network.default": "testnet"}, async () => {
network = await getChainId()
})

assert.equal(network, "testnet")
})
})
2 changes: 2 additions & 0 deletions packages/fcl/src/utils/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export {getChainId} from "./getChainId"

export function isAndroid() {
return (
typeof navigator !== "undefined" && /android/i.test(navigator.userAgent)
Expand Down
10 changes: 10 additions & 0 deletions packages/sdk/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,15 @@ const response = await sdk.send(await sdk.pipe(await sdk.build([
]), { node: "http://localhost:8080" })
```

### Get Network Parameters Usage

``` javascript
import * as sdk from "@onflow/sdk"
const response = await sdk.send(await sdk.build([
sdk.getNetworkParameters()
]), { node: "http://localhost:8080" })
```

## Flow JS-SDK Exposes

- [Top Level](./src)
Expand Down Expand Up @@ -504,6 +513,7 @@ const response = await sdk.send(await sdk.pipe(await sdk.build([
- [`sdk.getLatestBlock`](./src/build/build-get-latest-block.js)
- [`sdk.getTransactionStatus`](./src/build/build-get-transaction-status.js)
- [`sdk.getTransaction`](./src/build/build-get-transaction.js)
- [`sdk.getNetworkParameters`](./src/build/build-get-network-parameters.js)
- [`sdk.invariant`](./src/build/build-invariant.js)
- [`sdk.limit`](./src/build/build-limit.js)
- [`sdk.payer`](./src/build/build-payer.js)
Expand Down
10 changes: 10 additions & 0 deletions packages/sdk/src/build/build-get-network-parameters.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import {pipe, Ok, makeGetNetworkParameters} from "../interaction/interaction.js"

export function getNetworkParameters() {
return pipe([
makeGetNetworkParameters,
ix => {
return Ok(ix)
},
])
}
13 changes: 13 additions & 0 deletions packages/sdk/src/build/build-get-network-parameters.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import {
interaction,
isGetNetworkParameters,
} from "../interaction/interaction.js"
import {getNetworkParameters} from "./build-get-network-parameters.js"

describe("Build Get Network Parameters", () => {
test("Get Network Parameters", async () => {
let ix = await getNetworkParameters()(interaction())

expect(isGetNetworkParameters(ix)).toBe(true)
})
})
10 changes: 10 additions & 0 deletions packages/sdk/src/decode/decode.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,16 @@ export const decodeResponse = async (response, customDecoders = {}) => {
return response.transactionId
} else if (response.collection) {
return response.collection
} else if (response.networkParameters) {
const chainIdMap = {
"flow-testnet": "testnet",
"flow-mainnet": "mainnet",
"flow-emulator": "local",
}

return {
chainId: chainIdMap[response.networkParameters.chainId],
}
}

return null
Expand Down
Loading

0 comments on commit c20bc34

Please sign in to comment.