migrate to v2 (#118)
This commit is contained in:
@@ -19,6 +19,6 @@
|
||||
"types": "./dist/index.d.ts",
|
||||
"sideEffects": false,
|
||||
"peerDependencies": {
|
||||
"polkadot-api": ">=1.21.0"
|
||||
"polkadot-api": ">=2.0.0-rc.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
{
|
||||
"version": 0,
|
||||
"descriptorPath": ".papi/descriptors",
|
||||
"options": {
|
||||
"whitelist": ".papi/whitelist.ts"
|
||||
},
|
||||
"entries": {
|
||||
"polkadot_people": {
|
||||
"chain": "polkadot_people",
|
||||
|
||||
53
package.json
53
package.json
@@ -14,19 +14,18 @@
|
||||
"semi": false
|
||||
},
|
||||
"dependencies": {
|
||||
"@acala-network/chopsticks-core": "^1.2.5",
|
||||
"@acala-network/chopsticks-core": "^1.2.7",
|
||||
"@ledgerhq/hw-transport-webusb": "^6.30.0",
|
||||
"@monaco-editor/react": "^4.7.0",
|
||||
"@polkadot-api/descriptors": "file:.papi/descriptors",
|
||||
"@polkadot-api/json-rpc-provider-proxy": "^0.2.8",
|
||||
"@polkadot-api/metadata-builders": "^0.13.9",
|
||||
"@polkadot-api/observable-client": "^0.17.3",
|
||||
"@polkadot-api/react-builder": "0.3.11",
|
||||
"@polkadot-api/react-components": "^0.4.1",
|
||||
"@polkadot-api/substrate-bindings": "^0.17.0",
|
||||
"@polkadot-api/tx-utils": "^0.2.2",
|
||||
"@polkadot-api/utils": "^0.2.0",
|
||||
"@polkahub/ui-components": "0.3.2",
|
||||
"@polkadot-api/json-rpc-provider-proxy": "^0.3.0",
|
||||
"@polkadot-api/metadata-builders": "^0.13.11",
|
||||
"@polkadot-api/observable-client": "^0.18.1",
|
||||
"@polkadot-api/react-builder": "0.3.13",
|
||||
"@polkadot-api/react-components": "^0.4.2",
|
||||
"@polkadot-api/substrate-bindings": "^0.19.0",
|
||||
"@polkadot-api/tx-utils": "^0.2.4",
|
||||
"@polkahub/ui-components": "^0.5.0",
|
||||
"@radix-ui/react-accordion": "^1.2.12",
|
||||
"@radix-ui/react-dialog": "^1.1.15",
|
||||
"@radix-ui/react-label": "^2.1.8",
|
||||
@@ -44,41 +43,41 @@
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"idb-keyval": "^6.2.2",
|
||||
"lucide-react": "^0.562.0",
|
||||
"polkadot-api": "^1.23.3",
|
||||
"polkahub": "0.4.0",
|
||||
"react": "^19.2.3",
|
||||
"react-dom": "^19.2.3",
|
||||
"lucide-react": "^0.575.0",
|
||||
"polkadot-api": "^2.0.0-rc.2",
|
||||
"polkahub": "^0.5.0",
|
||||
"react": "^19.2.4",
|
||||
"react-dom": "^19.2.4",
|
||||
"react-portal": "^4.3.0",
|
||||
"react-router-dom": "^7.12.0",
|
||||
"react-svg": "^16.3.0",
|
||||
"react-router-dom": "^7.13.1",
|
||||
"react-svg": "^17.2.2",
|
||||
"react-virtuoso": "^4.18.1",
|
||||
"react18-json-view": "^0.2.9",
|
||||
"rxjs": "^7.8.2",
|
||||
"save-as": "^0.1.8",
|
||||
"tailwind-merge": "^3.4.0",
|
||||
"tailwind-merge": "^3.5.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"uuid": "^13.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.2",
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"@types/node": "^25.0.10",
|
||||
"@types/react": "^19.2.9",
|
||||
"@tailwindcss/vite": "^4.2.1",
|
||||
"@types/node": "^25.3.1",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@types/react-portal": "^4.0.7",
|
||||
"@vitejs/plugin-react": "^5.1.2",
|
||||
"@vitejs/plugin-react": "^5.1.4",
|
||||
"eslint": "^9.39.2",
|
||||
"eslint-plugin-react-hooks": "7.0.1",
|
||||
"eslint-plugin-react-refresh": "^0.4.26",
|
||||
"globals": "^17.0.0",
|
||||
"eslint-plugin-react-refresh": "^0.5.2",
|
||||
"globals": "^17.3.0",
|
||||
"prettier": "^3.8.1",
|
||||
"tailwindcss": "^4.1.18",
|
||||
"tailwindcss": "^4.2.1",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.53.1",
|
||||
"typescript-eslint": "^8.56.1",
|
||||
"vite": "^7.3.1"
|
||||
},
|
||||
"packageManager": "pnpm@10.28.1+sha512.7d7dbbca9e99447b7c3bf7a73286afaaf6be99251eb9498baefa7d406892f67b879adb3a1d7e687fc4ccc1a388c7175fbaae567a26ab44d1067b54fcb0d6a316",
|
||||
"packageManager": "pnpm@10.30.3+sha512.c961d1e0a2d8e354ecaa5166b822516668b7f44cb5bd95122d590dd81922f606f5473b6d23ec4a5be05e7fcd18e8488d47d978bbe981872f1145d06e9a740017",
|
||||
"pnpm": {
|
||||
"patchedDependencies": {
|
||||
"react18-json-view": "patches/react18-json-view.patch"
|
||||
|
||||
4140
pnpm-lock.yaml
generated
4140
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
import { BytesDisplay } from "@/codec-components/ViewCodec/CBytes"
|
||||
import { AccountIdDisplay } from "@/components/AccountIdDisplay"
|
||||
import { Binary, getSs58AddressInfo } from "polkadot-api"
|
||||
import { getSs58AddressInfo } from "polkadot-api"
|
||||
import { FC } from "react"
|
||||
import { EnumDisplay } from "./EnumDisplay"
|
||||
import { ArrayDisplay } from "./ListComponents"
|
||||
@@ -32,7 +32,7 @@ export const ViewValue: FC<{
|
||||
return <NumberDisplay value={value} />
|
||||
case "object": {
|
||||
if (value == null) return <>TODO</>
|
||||
if (value instanceof Binary) return <BytesDisplay value={value} />
|
||||
if (value instanceof Uint8Array) return <BytesDisplay value={value} />
|
||||
if (Array.isArray(value)) return <ArrayDisplay value={value} />
|
||||
if ("type" in value && typeof value.type === "string" && "value" in value)
|
||||
return <EnumDisplay value={value as any} />
|
||||
|
||||
@@ -1,80 +1,87 @@
|
||||
import type { Blockchain } from "@acala-network/chopsticks-core"
|
||||
import { getSyncProvider } from "@polkadot-api/json-rpc-provider-proxy"
|
||||
import { Blockchain, ChopsticksProvider } from "@acala-network/chopsticks-core"
|
||||
import {
|
||||
getSyncProvider,
|
||||
InnerJsonRpcProvider,
|
||||
} from "@polkadot-api/json-rpc-provider-proxy"
|
||||
import { blockHeader } from "@polkadot-api/substrate-bindings"
|
||||
import { JsonRpcProvider } from "polkadot-api/ws-provider/web"
|
||||
import type { JsonRpcProvider } from "polkadot-api"
|
||||
import { BehaviorSubject } from "rxjs"
|
||||
|
||||
export const chopsticksInstance$ = new BehaviorSubject<Blockchain | null>(null)
|
||||
|
||||
export const createChopsticksProvider = (endpoint: string) =>
|
||||
withChopsticksEnhancer(
|
||||
getSyncProvider(async () => {
|
||||
const { ChopsticksProvider, setup } = await import(
|
||||
"@acala-network/chopsticks-core"
|
||||
)
|
||||
getSyncProvider((onReady) => {
|
||||
let isRunning = true
|
||||
let chain: Blockchain
|
||||
|
||||
chopsticksInstance$.getValue()?.close()
|
||||
const chain = await setup({
|
||||
endpoint,
|
||||
mockSignatureHost: true,
|
||||
})
|
||||
chopsticksInstance$.next(chain)
|
||||
|
||||
const innerProvider = new ChopsticksProvider(chain)
|
||||
return (onMessage) => {
|
||||
return {
|
||||
send: async (message: string) => {
|
||||
const parsed = JSON.parse(message)
|
||||
|
||||
if (parsed.method === "chainHead_v1_follow") {
|
||||
const subscription = await innerProvider.subscribe(
|
||||
"chainHead_v1_followEvent",
|
||||
parsed.method,
|
||||
parsed.params,
|
||||
(err, result) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
return
|
||||
}
|
||||
onMessage(
|
||||
JSON.stringify({
|
||||
const getProvider =
|
||||
(
|
||||
innerProvider: InstanceType<typeof ChopsticksProvider>,
|
||||
): InnerJsonRpcProvider =>
|
||||
(onMessage) => {
|
||||
return {
|
||||
send: async (msg) => {
|
||||
if (msg.method === "chainHead_v1_follow") {
|
||||
const subscription = await innerProvider.subscribe(
|
||||
"chainHead_v1_followEvent",
|
||||
msg.method,
|
||||
msg.params,
|
||||
(err, result) => {
|
||||
if (err) {
|
||||
console.error(err)
|
||||
return
|
||||
}
|
||||
onMessage({
|
||||
jsonrpc: "2.0",
|
||||
method: "chainHead_v1_followEvent",
|
||||
params: {
|
||||
subscription,
|
||||
result,
|
||||
},
|
||||
}),
|
||||
)
|
||||
},
|
||||
)
|
||||
onMessage(
|
||||
JSON.stringify({
|
||||
})
|
||||
},
|
||||
)
|
||||
onMessage({
|
||||
jsonrpc: "2.0",
|
||||
id: parsed.id,
|
||||
id: msg.id!,
|
||||
result: subscription,
|
||||
}),
|
||||
)
|
||||
return
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const response = await innerProvider.send(
|
||||
parsed.method,
|
||||
parsed.params,
|
||||
)
|
||||
onMessage(
|
||||
JSON.stringify({
|
||||
const response = await innerProvider.send(msg.method, msg.params)
|
||||
onMessage({
|
||||
jsonrpc: "2.0",
|
||||
id: parsed.id,
|
||||
id: msg.id!,
|
||||
result: response,
|
||||
}),
|
||||
)
|
||||
},
|
||||
disconnect: () => {
|
||||
chain?.close()
|
||||
chopsticksInstance$.next(null)
|
||||
},
|
||||
})
|
||||
},
|
||||
disconnect: () => {
|
||||
chain.close()
|
||||
chopsticksInstance$.next(null)
|
||||
},
|
||||
}
|
||||
}
|
||||
;(async () => {
|
||||
try {
|
||||
const { ChopsticksProvider, setup } =
|
||||
await import("@acala-network/chopsticks-core")
|
||||
|
||||
chain = await setup({
|
||||
endpoint,
|
||||
mockSignatureHost: true,
|
||||
})
|
||||
if (isRunning) {
|
||||
onReady(getProvider(new ChopsticksProvider(chain)))
|
||||
chopsticksInstance$.next(chain)
|
||||
} else chain.close()
|
||||
} catch {
|
||||
if (isRunning) onReady(null)
|
||||
}
|
||||
})()
|
||||
return () => {
|
||||
isRunning = false
|
||||
}
|
||||
}),
|
||||
)
|
||||
@@ -101,25 +108,21 @@ const withChopsticksEnhancer =
|
||||
previousNumber !== null &&
|
||||
currentNumber > previousNumber + 1
|
||||
) {
|
||||
onMessage(
|
||||
JSON.stringify({
|
||||
...waitingForNumber,
|
||||
params: {
|
||||
...waitingForNumber.params,
|
||||
result: {
|
||||
event: "stop",
|
||||
},
|
||||
onMessage({
|
||||
...waitingForNumber,
|
||||
params: {
|
||||
...waitingForNumber.params,
|
||||
result: {
|
||||
event: "stop",
|
||||
},
|
||||
}),
|
||||
)
|
||||
inner.send(
|
||||
JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
id: "chopsticks-stopped",
|
||||
method: "chainHead_v1_unfollow",
|
||||
params: [waitingForNumber.params.subscription],
|
||||
}),
|
||||
)
|
||||
},
|
||||
})
|
||||
inner.send({
|
||||
jsonrpc: "2.0",
|
||||
id: "chopsticks-stopped",
|
||||
method: "chainHead_v1_unfollow",
|
||||
params: [waitingForNumber.params.subscription],
|
||||
})
|
||||
messageQueue.length = 0
|
||||
previousNumber = currentNumber
|
||||
waitingForNumber = null
|
||||
@@ -128,7 +131,7 @@ const withChopsticksEnhancer =
|
||||
previousNumber = currentNumber
|
||||
|
||||
if (waitingForNumber) {
|
||||
onMessage(JSON.stringify(waitingForNumber))
|
||||
onMessage(waitingForNumber)
|
||||
waitingForNumber = null
|
||||
}
|
||||
|
||||
@@ -151,29 +154,23 @@ const withChopsticksEnhancer =
|
||||
const { blockHash } = parsed.params.result
|
||||
waitingForNumber = parsed
|
||||
|
||||
inner.send(
|
||||
JSON.stringify({
|
||||
jsonrpc: "2.0",
|
||||
id: "chopsticks-header-" + blockHash,
|
||||
method: "chainHead_v1_header",
|
||||
params: [parsed.params.subscription, blockHash],
|
||||
}),
|
||||
)
|
||||
inner.send({
|
||||
jsonrpc: "2.0",
|
||||
id: "chopsticks-header-" + blockHash,
|
||||
method: "chainHead_v1_header",
|
||||
params: [parsed.params.subscription, blockHash],
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
onMessage(JSON.stringify(parsed))
|
||||
onMessage(parsed)
|
||||
if (messageQueue.length) {
|
||||
const [next] = messageQueue.splice(0, 1)
|
||||
processMessage(next)
|
||||
}
|
||||
}
|
||||
|
||||
const inner = parent((msg) => {
|
||||
const parsed = JSON.parse(msg)
|
||||
|
||||
processMessage(parsed)
|
||||
})
|
||||
const inner = parent(processMessage)
|
||||
|
||||
return {
|
||||
send(message) {
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
NOTIN,
|
||||
} from "@polkadot-api/react-builder"
|
||||
import { u8 } from "@polkadot-api/substrate-bindings"
|
||||
import { toHex } from "@polkadot-api/utils"
|
||||
import { toHex } from "polkadot-api/utils"
|
||||
import { useStateObservable } from "@react-rxjs/core"
|
||||
import { FC } from "react"
|
||||
import { isActive$ } from "../common/paths.state"
|
||||
|
||||
@@ -3,8 +3,8 @@ import { BinaryEditButton } from "@/components/BinaryEditButton"
|
||||
import { CopyText } from "@/components/Copy"
|
||||
import { ExpandBtn } from "@/components/Expand"
|
||||
import { CodecComponentType, NOTIN } from "@polkadot-api/react-builder"
|
||||
import { Binary, HexString } from "@polkadot-api/substrate-bindings"
|
||||
import { toHex } from "@polkadot-api/utils"
|
||||
import { HexString } from "@polkadot-api/substrate-bindings"
|
||||
import { fromHex, toHex } from "polkadot-api/utils"
|
||||
import { ComponentProps, FC, useState } from "react"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
import { EditCodec } from "../EditCodec"
|
||||
@@ -24,7 +24,7 @@ export const BinaryDisplay: FC<
|
||||
if (value.type === CodecComponentType.Initial) {
|
||||
if (!value.value) return null
|
||||
return typeof value.value === "string"
|
||||
? Binary.fromHex(value.value).asBytes()
|
||||
? fromHex(value.value)
|
||||
: value.value
|
||||
}
|
||||
if (value.value.empty || !value.value.encoded) return null
|
||||
@@ -43,7 +43,7 @@ export const BinaryDisplay: FC<
|
||||
className={twMerge(
|
||||
"binary-display-codec",
|
||||
"text-sm tabular-nums overflow-hidden flex-1",
|
||||
wrap ? "break-words" : "whitespace-nowrap text-ellipsis h-5",
|
||||
wrap ? "wrap-break-word" : "whitespace-nowrap text-ellipsis h-5",
|
||||
)}
|
||||
>
|
||||
{isEmpty ? (
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { getBytesFormat } from "@/components/BinaryInput"
|
||||
import { SwitchBinary } from "@/components/Icons"
|
||||
import { ViewBytes } from "@polkadot-api/react-builder"
|
||||
import { Binary } from "polkadot-api"
|
||||
import { FC, useState } from "react"
|
||||
import { useReportBinary } from "./CopyBinary"
|
||||
import { toHex } from "polkadot-api/utils"
|
||||
|
||||
export const CBytes: ViewBytes = ({ value, encodedValue }) => {
|
||||
useReportBinary(encodedValue)
|
||||
@@ -11,7 +11,7 @@ export const CBytes: ViewBytes = ({ value, encodedValue }) => {
|
||||
return <BytesDisplay value={value} />
|
||||
}
|
||||
|
||||
export const BytesDisplay: FC<{ value: Binary }> = ({ value }) => {
|
||||
export const BytesDisplay: FC<{ value: Uint8Array }> = ({ value }) => {
|
||||
const [forceBinary, setForceBinary] = useState(false)
|
||||
|
||||
const format = getBytesFormat(value)
|
||||
@@ -27,7 +27,7 @@ export const BytesDisplay: FC<{ value: Binary }> = ({ value }) => {
|
||||
<SwitchBinary size={24} />
|
||||
</button>
|
||||
) : null}
|
||||
{forceBinary ? value.asHex() : format.value}
|
||||
{forceBinary ? toHex(value) : format.value}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CopyText } from "@/components/Copy"
|
||||
import { Binary } from "polkadot-api"
|
||||
import { toHex } from "polkadot-api/utils"
|
||||
import {
|
||||
createContext,
|
||||
FC,
|
||||
@@ -55,7 +55,7 @@ export const CopyBinary: FC<{ value: Uint8Array; visible?: boolean }> = ({
|
||||
visible = true,
|
||||
}) => (
|
||||
<CopyText
|
||||
text={Binary.fromBytes(value).asHex()}
|
||||
text={toHex(value)}
|
||||
className={twMerge("transition-opacity", !visible ? "opacity-0" : "")}
|
||||
binary
|
||||
/>
|
||||
|
||||
@@ -5,7 +5,6 @@ import {
|
||||
import { Modal } from "@/components/Modal"
|
||||
import { useGenericSynchronizeInput } from "@/components/useSynchroniseInput"
|
||||
import { NOTIN } from "@polkadot-api/react-builder"
|
||||
import { Binary } from "@polkadot-api/substrate-bindings"
|
||||
import { Download, FileUp } from "lucide-react"
|
||||
import { ComponentProps, FC, useMemo, useState } from "react"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
@@ -13,6 +12,7 @@ import { twMerge } from "tailwind-merge"
|
||||
import { saveAs } from "save-as"
|
||||
import { BinaryEdit } from "./Icons"
|
||||
import { ActionButton } from "./ActionButton"
|
||||
import { fromHex, toHex } from "polkadot-api/utils"
|
||||
|
||||
export interface BinaryEditProps {
|
||||
initialValue?: Uint8Array
|
||||
@@ -80,17 +80,13 @@ const BinaryEditModalContent: FC<
|
||||
const [inputValue, setInputValue] = useGenericSynchronizeInput(
|
||||
value,
|
||||
setValue as any,
|
||||
(input) => parseInput(input).asBytes(),
|
||||
parseInput,
|
||||
"" as string | Uint8Array,
|
||||
(value) => {
|
||||
if (value.length > MAX_DISPLAY_SIZE) return ""
|
||||
return Binary.fromBytes(value).asHex()
|
||||
return toHex(value)
|
||||
},
|
||||
(input, value) =>
|
||||
checkEqualInputBinary(
|
||||
parseInput(input),
|
||||
value === NOTIN ? NOTIN : Binary.fromBytes(value),
|
||||
),
|
||||
(input, value) => checkEqualInputBinary(parseInput(input), value),
|
||||
)
|
||||
|
||||
const placeholder =
|
||||
@@ -158,7 +154,7 @@ const BinaryEditModalContent: FC<
|
||||
<BinaryFileInput
|
||||
validate={validateFile}
|
||||
onError={() => setError("Error loading file")}
|
||||
onLoaded={(value) => setValue(value.asBytes())}
|
||||
onLoaded={setValue}
|
||||
/>
|
||||
</label>
|
||||
</div>
|
||||
@@ -186,6 +182,4 @@ const BinaryEditModalContent: FC<
|
||||
}
|
||||
|
||||
const parseInput = (value: string | Uint8Array) =>
|
||||
value instanceof Uint8Array
|
||||
? Binary.fromBytes(value)
|
||||
: Binary.fromHex(value.startsWith("0x") ? value : `0x${value}`)
|
||||
value instanceof Uint8Array ? value : fromHex(value)
|
||||
|
||||
@@ -7,17 +7,18 @@ import { twMerge } from "tailwind-merge"
|
||||
import { SwitchBinary } from "./Icons"
|
||||
import { TextInputField } from "./TextInputField"
|
||||
import { useGenericSynchronizeInput } from "./useSynchroniseInput"
|
||||
import { fromHex, toHex } from "polkadot-api/utils"
|
||||
|
||||
export const BinaryInput: React.FC<{
|
||||
encodedValue: Binary | NOTIN
|
||||
onValueChanged: (newValue: Binary | NOTIN) => boolean
|
||||
encodedValue: Uint8Array | NOTIN
|
||||
onValueChanged: (newValue: Uint8Array | NOTIN) => boolean
|
||||
len?: number
|
||||
}> = ({ encodedValue, onValueChanged, len }) => {
|
||||
const [localInput, setLocalInput] = useGenericSynchronizeInput(
|
||||
encodedValue,
|
||||
onValueChanged,
|
||||
(value) => validate(parseValue(value), len),
|
||||
"" as string | Binary,
|
||||
"" as string | Uint8Array,
|
||||
serializeValue,
|
||||
checkEqualInputBinary,
|
||||
)
|
||||
@@ -44,7 +45,7 @@ export const BinaryInput: React.FC<{
|
||||
}
|
||||
|
||||
const parsed = parseValue(inputValue)
|
||||
const length = parsed === NOTIN ? null : parsed.asBytes().length
|
||||
const length = parsed === NOTIN ? null : parsed.length
|
||||
|
||||
const oddHexLength =
|
||||
typeof localInput === "string" &&
|
||||
@@ -82,9 +83,9 @@ export const BinaryInput: React.FC<{
|
||||
type="button"
|
||||
onClick={() => {
|
||||
if (inputValue.startsWith("0x")) {
|
||||
setLocalInput(serializeValue(Binary.fromHex(inputValue)))
|
||||
setLocalInput(serializeValue(fromHex(inputValue)))
|
||||
} else {
|
||||
setLocalInput(Binary.fromText(inputValue).asHex())
|
||||
setLocalInput(toHex(Binary.fromText(inputValue)))
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -110,7 +111,7 @@ export const BinaryInput: React.FC<{
|
||||
|
||||
export const BinaryFileInput: FC<{
|
||||
validate: (file: File) => boolean
|
||||
onLoaded: (value: Binary) => void
|
||||
onLoaded: (value: Uint8Array) => void
|
||||
onError: () => void
|
||||
}> = ({ validate, onLoaded, onError }) => {
|
||||
const loadFile = async (file: File) => {
|
||||
@@ -124,7 +125,7 @@ export const BinaryFileInput: FC<{
|
||||
reader.onerror = reject
|
||||
reader.readAsArrayBuffer(file)
|
||||
})
|
||||
onLoaded(Binary.fromBytes(new Uint8Array(buffer)))
|
||||
onLoaded(new Uint8Array(buffer))
|
||||
} catch (ex) {
|
||||
console.error(ex)
|
||||
onError()
|
||||
@@ -143,19 +144,22 @@ export const BinaryFileInput: FC<{
|
||||
)
|
||||
}
|
||||
|
||||
const validate = (value: Binary | NOTIN, len?: number): Binary | NOTIN => {
|
||||
const validate = (
|
||||
value: Uint8Array | NOTIN,
|
||||
len?: number,
|
||||
): Uint8Array | NOTIN => {
|
||||
if (!len || value === NOTIN) return value
|
||||
return value.asBytes().length !== len ? NOTIN : value
|
||||
return value.length !== len ? NOTIN : value
|
||||
}
|
||||
|
||||
const parseValue = (value: string | Binary): Binary | NOTIN => {
|
||||
if (value instanceof Binary) return value
|
||||
const parseValue = (value: string | Uint8Array): Uint8Array | NOTIN => {
|
||||
if (value instanceof Uint8Array) return value
|
||||
|
||||
if (value.trim() === "") return Binary.fromText("")
|
||||
|
||||
if (value.startsWith("0x")) {
|
||||
try {
|
||||
return Binary.fromHex(value)
|
||||
return fromHex(value)
|
||||
} catch (_) {
|
||||
return NOTIN
|
||||
}
|
||||
@@ -164,40 +168,35 @@ const parseValue = (value: string | Binary): Binary | NOTIN => {
|
||||
return Binary.fromText(value)
|
||||
}
|
||||
|
||||
const serializeValue = (value: Binary): string | Binary => {
|
||||
const bytes = value.asBytes()
|
||||
if (bytes.length === 0) return ""
|
||||
if (bytes.length > 5 * 1024 * 1024) return value
|
||||
const serializeValue = (value: Uint8Array): string | Uint8Array => {
|
||||
if (value.length === 0) return ""
|
||||
if (value.length > 5 * 1024 * 1024) return value
|
||||
|
||||
return bytesToString(value)
|
||||
}
|
||||
|
||||
const textDecoder = new TextDecoder("utf-8", { fatal: true })
|
||||
export const getBytesFormat = (value: Binary) => {
|
||||
export const getBytesFormat = (value: Uint8Array) => {
|
||||
try {
|
||||
const bytes = value.asBytes()
|
||||
if (bytes.slice(0, 5).every((b) => b < 32)) throw null
|
||||
if (value.slice(0, 5).every((b) => b < 32)) throw null
|
||||
return {
|
||||
type: "text",
|
||||
value: textDecoder.decode(bytes),
|
||||
value: textDecoder.decode(value),
|
||||
}
|
||||
} catch (_) {
|
||||
return {
|
||||
type: "hex",
|
||||
value: value.asHex(),
|
||||
value: toHex(value),
|
||||
}
|
||||
}
|
||||
}
|
||||
export const bytesToString = (value: Binary) => getBytesFormat(value).value
|
||||
export const bytesToString = (value: Uint8Array) => getBytesFormat(value).value
|
||||
|
||||
export const checkEqualInputBinary = (
|
||||
input: string | Binary,
|
||||
value: Binary | typeof NOTIN,
|
||||
input: string | Uint8Array,
|
||||
value: Uint8Array | typeof NOTIN,
|
||||
) => {
|
||||
const parsed = parseValue(input)
|
||||
if (parsed === NOTIN || value === NOTIN) return true
|
||||
const inputBytes = parsed.asBytes()
|
||||
const valueBytes = value.asBytes()
|
||||
|
||||
return byteArraysAreEqual(inputBytes, valueBytes)
|
||||
return byteArraysAreEqual(parsed, value)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { bytesToString } from "@/components/BinaryInput"
|
||||
import { Binary } from "@polkadot-api/substrate-bindings"
|
||||
import { FC } from "react"
|
||||
import ReactJson from "react18-json-view"
|
||||
import "react18-json-view/src/dark.css"
|
||||
@@ -18,14 +17,14 @@ export const JsonDisplay: FC<{
|
||||
src={src}
|
||||
dark={theme === "dark"}
|
||||
theme="a11y"
|
||||
replacer={(v) => (v instanceof Binary ? bytesToString(v) : v)}
|
||||
replacer={(v) => (v instanceof Uint8Array ? bytesToString(v) : v)}
|
||||
customizeCopy={(v) =>
|
||||
JSON.stringify(
|
||||
v,
|
||||
(_, v) =>
|
||||
typeof v === "bigint"
|
||||
? `${v}n`
|
||||
: v instanceof Binary
|
||||
: v instanceof Uint8Array
|
||||
? bytesToString(v)
|
||||
: v,
|
||||
2,
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
} from "@react-rxjs/core"
|
||||
import { Send } from "lucide-react"
|
||||
import { CompatibilityLevel, SS58String } from "polkadot-api"
|
||||
import { toHex } from "polkadot-api/utils"
|
||||
import {
|
||||
Account,
|
||||
ledgerProviderId,
|
||||
@@ -77,7 +78,7 @@ const AccountCard: FC<{
|
||||
<div className="flex justify-between items-start overflow-hidden">
|
||||
<AccountIdDisplay
|
||||
value={account.address}
|
||||
className="shrink-1 overflow-hidden"
|
||||
className="shrink overflow-hidden"
|
||||
/>
|
||||
<SourceTag account={account} />
|
||||
</div>
|
||||
@@ -127,7 +128,7 @@ const balance$ = state(
|
||||
typedApi.query.System.Account.watchValue(accountId),
|
||||
),
|
||||
map((account) => {
|
||||
const { reserved, free, frozen } = account.data
|
||||
const { reserved, free, frozen } = account.value.data
|
||||
const total = reserved + free
|
||||
|
||||
// TODO ED
|
||||
@@ -156,12 +157,12 @@ const getTransferCallData$ = state(
|
||||
const tokenDecimals = chainProperties?.tokenDecimals
|
||||
|
||||
if (tokenDecimals == null) return null
|
||||
const token = await typedApi.compatibilityToken
|
||||
|
||||
const staticApis = await typedApi.getStaticApis()
|
||||
|
||||
if (
|
||||
!typedApi.tx.Balances.transfer_keep_alive.isCompatible(
|
||||
!staticApis.compat.tx.Balances.transfer_keep_alive.isCompatible(
|
||||
CompatibilityLevel.BackwardsCompatible,
|
||||
token,
|
||||
)
|
||||
) {
|
||||
return null
|
||||
@@ -170,12 +171,12 @@ const getTransferCallData$ = state(
|
||||
return (dest: SS58String) => {
|
||||
const value = 10n ** BigInt(tokenDecimals)
|
||||
|
||||
return typedApi.tx.Balances.transfer_keep_alive({
|
||||
dest: MultiAddress.Id(dest),
|
||||
value,
|
||||
})
|
||||
.getEncodedData(token)
|
||||
.asHex()
|
||||
return toHex(
|
||||
staticApis.tx.Balances.transfer_keep_alive.getCallData({
|
||||
dest: MultiAddress.Id(dest),
|
||||
value,
|
||||
}),
|
||||
)
|
||||
}
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -14,7 +14,7 @@ import { BlockStorageDiff } from "./BlockStorageDiff"
|
||||
import { ApplyExtrinsicEvent, Extrinsic } from "./Extrinsic"
|
||||
import { getHashParams } from "@/hashParams"
|
||||
import { Blake2256 } from "@polkadot-api/substrate-bindings"
|
||||
import { fromHex, toHex } from "@polkadot-api/utils"
|
||||
import { toHex } from "polkadot-api/utils"
|
||||
|
||||
const blockExtrinsics$ = state((hash: string) => {
|
||||
const body$ = blockInfoState$(hash).pipe(
|
||||
@@ -31,7 +31,7 @@ const blockExtrinsics$ = state((hash: string) => {
|
||||
map(([body, { txDecoder }]) =>
|
||||
body.map((raw, idx) => ({
|
||||
idx,
|
||||
hash: toHex(Blake2256(fromHex(raw))),
|
||||
hash: toHex(Blake2256(raw)),
|
||||
...txDecoder(raw),
|
||||
})),
|
||||
),
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
u8,
|
||||
Vector,
|
||||
} from "@polkadot-api/substrate-bindings"
|
||||
import { toHex } from "@polkadot-api/utils"
|
||||
import { toHex } from "polkadot-api/utils"
|
||||
import { state, useStateObservable } from "@react-rxjs/core"
|
||||
import { Binary, Codec } from "polkadot-api"
|
||||
import { FC } from "react"
|
||||
@@ -37,12 +37,12 @@ const blockDiff$ = state(
|
||||
|
||||
const palletKeys = Object.fromEntries(
|
||||
lookup.metadata.pallets.map((pallet) => [
|
||||
toHex(Twox128(Binary.fromText(pallet.name).asBytes())).slice(2),
|
||||
toHex(Twox128(Binary.fromText(pallet.name))).slice(2),
|
||||
{
|
||||
name: pallet.name,
|
||||
entries: Object.fromEntries(
|
||||
pallet.storage?.items.map((item) => [
|
||||
toHex(Twox128(Binary.fromText(item.name).asBytes())).slice(2),
|
||||
toHex(Twox128(Binary.fromText(item.name))).slice(2),
|
||||
item.name,
|
||||
]) ?? [],
|
||||
),
|
||||
@@ -149,7 +149,7 @@ export const BlockStorageDiff: FC<{
|
||||
? `(${JSON.stringify(v, (_, v) =>
|
||||
typeof v === "bigint"
|
||||
? `${v}n`
|
||||
: v instanceof Binary
|
||||
: v instanceof Uint8Array
|
||||
? bytesToString(v)
|
||||
: v,
|
||||
)})`
|
||||
@@ -176,7 +176,7 @@ export const BlockStorageDiff: FC<{
|
||||
)
|
||||
}
|
||||
|
||||
const strToHex = (v: string) => Binary.fromText(v).asHex()
|
||||
const strToHex = (v: string) => toHex(Binary.fromText(v))
|
||||
const wellKnownKeys: Record<
|
||||
string,
|
||||
{
|
||||
|
||||
@@ -9,7 +9,8 @@ import { shortStr } from "@/utils"
|
||||
import { SystemEvent } from "@polkadot-api/observable-client"
|
||||
import { DecodedExtrinsic } from "@polkadot-api/tx-utils"
|
||||
import { Dot, Edit } from "lucide-react"
|
||||
import { Binary, Enum, HexString, SS58String } from "polkadot-api"
|
||||
import { Enum, HexString, SS58String } from "polkadot-api"
|
||||
import { toHex } from "polkadot-api/utils"
|
||||
import { FC, useEffect, useRef, useState } from "react"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
@@ -41,13 +42,13 @@ export const Extrinsic: FC<{
|
||||
{extrinsic.idx}. {extrinsic.call.type}.{extrinsic.call.value.type}
|
||||
</button>
|
||||
<div className="flex gap-2 items-center">
|
||||
<CopyBinary value={extrinsic.callData.asBytes()} />
|
||||
{extrinsic.callData.asBytes().length > 1024 ? (
|
||||
<CopyBinary value={extrinsic.callData} />
|
||||
{extrinsic.callData.length > 1024 ? (
|
||||
<span className="opacity-50">
|
||||
<Edit size={14} />
|
||||
</span>
|
||||
) : (
|
||||
<Link to={"/extrinsics#data=" + extrinsic.callData.asHex()}>
|
||||
<Link to={"/extrinsics#data=" + toHex(extrinsic.callData)}>
|
||||
<Edit size={14} />
|
||||
</Link>
|
||||
)}
|
||||
@@ -107,7 +108,7 @@ const SignedExtensions: FC<{ extra: Record<string, unknown> }> = ({
|
||||
const SignedExtension: FC<{ id: string; value: unknown }> = ({ id, value }) => {
|
||||
const [expanded, setExpanded] = useState(false)
|
||||
const inlineJson = JSON.stringify(value, (_, v) =>
|
||||
typeof v === "bigint" ? String(v) : v instanceof Binary ? v.asHex() : v,
|
||||
typeof v === "bigint" ? String(v) : v instanceof Uint8Array ? toHex(v) : v,
|
||||
)
|
||||
|
||||
if (!inlineJson || inlineJson.length < 40) {
|
||||
|
||||
@@ -50,7 +50,7 @@ const epochFromCall$ = runtimeCtx$.pipe(
|
||||
}
|
||||
return (
|
||||
getFromApi("BabeApi", "configuration")?.then((r) =>
|
||||
Number(r.epoch_length),
|
||||
Number((r as any).epoch_length),
|
||||
) ?? of(null)
|
||||
)
|
||||
}),
|
||||
@@ -72,7 +72,7 @@ const epochStartBlock$ = state(
|
||||
? client
|
||||
.getUnsafeApi()
|
||||
.query[pallet][entry].watchValue()
|
||||
.pipe(map(([, duration]) => Number(duration)))
|
||||
.pipe(map(({ value }) => Number((value as any)[1])))
|
||||
: of(null)
|
||||
}),
|
||||
),
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import { chopsticksInstance$ } from "@/chopsticks/chopsticks"
|
||||
import { chainClient$, client$ } from "@/state/chains/chain.state"
|
||||
import { SystemEvent } from "@polkadot-api/observable-client"
|
||||
import { blockHeader } from "@polkadot-api/substrate-bindings"
|
||||
import { blockHeader, SizedHex } from "@polkadot-api/substrate-bindings"
|
||||
import { liftSuspense, state } from "@react-rxjs/core"
|
||||
import { combineKeys, partitionByKey } from "@react-rxjs/utils"
|
||||
import {
|
||||
BlockHeader,
|
||||
FixedSizeBinary,
|
||||
HexString,
|
||||
PolkadotClient,
|
||||
BlockInfo as RawBlockInfo,
|
||||
} from "polkadot-api"
|
||||
import { fromHex } from "polkadot-api/utils"
|
||||
import {
|
||||
catchError,
|
||||
combineLatest,
|
||||
@@ -56,7 +56,7 @@ export interface BlockInfo {
|
||||
hash: string
|
||||
parent: string
|
||||
number: number
|
||||
body: string[] | null
|
||||
body: Uint8Array[] | null
|
||||
events: SystemEvent[] | null
|
||||
header: BlockHeader | null
|
||||
status: BlockState
|
||||
@@ -93,7 +93,7 @@ export const [blockInfo$, recordedBlocks$] = partitionByKey(
|
||||
hash: of(hash),
|
||||
parent: of(parent),
|
||||
number: of(number),
|
||||
body: client.watchBlockBody(hash).pipe(
|
||||
body: client.getBlockBody$(hash).pipe(
|
||||
startWith(null),
|
||||
catchError((err) => {
|
||||
console.error("fetch body failed", err)
|
||||
@@ -103,7 +103,7 @@ export const [blockInfo$, recordedBlocks$] = partitionByKey(
|
||||
events: from(
|
||||
client.getUnsafeApi().query.System.Events.getValue({
|
||||
at: hash,
|
||||
}),
|
||||
}) as Promise<SystemEvent[]>,
|
||||
).pipe(
|
||||
startWith(null),
|
||||
catchError((err) => {
|
||||
@@ -154,10 +154,10 @@ const getUnpinnedBlockInfo$ = (hash: string): Observable<BlockInfo> =>
|
||||
),
|
||||
),
|
||||
),
|
||||
body: client.watchBlockBody(hash),
|
||||
body: client.getBlockBody$(hash),
|
||||
events: client.getUnsafeApi().query.System.Events.getValue({
|
||||
at: hash,
|
||||
}),
|
||||
}) as Promise<SystemEvent[]>,
|
||||
}).pipe(
|
||||
map(({ headerAndStatus: { header, status }, body, events }) => ({
|
||||
hash: hash,
|
||||
@@ -221,7 +221,7 @@ const getUnpinnedBlockInfoFallback$ = (
|
||||
({ block: { extrinsics, header }, status, number }): BlockInfo => ({
|
||||
hash,
|
||||
parent: header.parentHash,
|
||||
body: extrinsics,
|
||||
body: extrinsics.map(fromHex),
|
||||
events: null,
|
||||
header: {
|
||||
digests: header.digest.logs
|
||||
@@ -254,7 +254,7 @@ export const inMemoryBlocks$ = state(
|
||||
)
|
||||
inMemoryBlocks$.pipe(liftSuspense()).subscribe()
|
||||
|
||||
export const blockHash$ = (hashOrHeight: string) =>
|
||||
export const blockHash$ = (hashOrHeight: string): Observable<SizedHex<32>> =>
|
||||
hashOrHeight.length > 63
|
||||
? of(hashOrHeight.startsWith("0x") ? hashOrHeight : `0x${hashOrHeight}`)
|
||||
: client$.pipe(
|
||||
@@ -268,11 +268,13 @@ export const blockHash$ = (hashOrHeight: string) =>
|
||||
if (x.length) return x[0]
|
||||
throw null
|
||||
}),
|
||||
catchError(() =>
|
||||
client
|
||||
.getUnsafeApi()
|
||||
.query.System.BlockHash.getValue(Number(hashOrHeight))
|
||||
.then((x: FixedSizeBinary<32>) => x.asHex()),
|
||||
catchError(
|
||||
() =>
|
||||
client
|
||||
.getUnsafeApi()
|
||||
.query.System.BlockHash.getValue(
|
||||
Number(hashOrHeight),
|
||||
) as Promise<SizedHex<32>>,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -36,7 +36,7 @@ const fromCall$ = runtimeCtx$.pipe(
|
||||
return (
|
||||
getFromApi("AuraApi", "slot_duration")?.then((r) => Number(r)) ??
|
||||
getFromApi("BabeApi", "configuration")?.then((r) =>
|
||||
Number(r.slot_duration),
|
||||
Number((r as any).slot_duration),
|
||||
) ??
|
||||
of(null)
|
||||
)
|
||||
|
||||
@@ -8,8 +8,7 @@ import {
|
||||
CodecComponentType,
|
||||
CodecComponentValue,
|
||||
} from "@polkadot-api/react-builder"
|
||||
import { Binary } from "@polkadot-api/substrate-bindings"
|
||||
import { toHex } from "@polkadot-api/utils"
|
||||
import { fromHex, toHex } from "polkadot-api/utils"
|
||||
import { state, useStateObservable } from "@react-rxjs/core"
|
||||
import { useLayoutEffect, useState } from "react"
|
||||
import { useLocation } from "react-router-dom"
|
||||
@@ -143,7 +142,7 @@ export const Extrinsics = withSubscribe(
|
||||
<JsonMode
|
||||
value={
|
||||
typeof binaryValue === "string"
|
||||
? Binary.fromHex(binaryValue).asBytes()
|
||||
? fromHex(binaryValue)
|
||||
: binaryValue
|
||||
}
|
||||
decode={extrinsicProps.codec.dec}
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/components/ui/dialog"
|
||||
import { toHex } from "@polkadot-api/utils"
|
||||
import { toHex } from "polkadot-api/utils"
|
||||
import { HexString } from "polkadot-api"
|
||||
import React, { lazy, Suspense, useState } from "react"
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { trackSignedTx, trackUnsignedTx } from "@/pages/Transactions"
|
||||
import { unsafeApi$ } from "@/state/chains/chain.state"
|
||||
import { selectedAccount$ } from "@/state/polkahub"
|
||||
import { compactNumber } from "@polkadot-api/substrate-bindings"
|
||||
import { fromHex, mergeUint8, toHex } from "@polkadot-api/utils"
|
||||
import { fromHex, mergeUint8 } from "polkadot-api/utils"
|
||||
import { AccountPicker } from "@polkahub/ui-components"
|
||||
import { useStateObservable } from "@react-rxjs/core"
|
||||
import { Binary } from "polkadot-api"
|
||||
@@ -72,7 +72,7 @@ const SubmitUnsigned: FC<{ callData: string; onClose: () => void }> = ({
|
||||
new Uint8Array([4]),
|
||||
data,
|
||||
])
|
||||
trackUnsignedTx(toHex(unsignedTx))
|
||||
trackUnsignedTx(unsignedTx)
|
||||
onClose()
|
||||
}}
|
||||
className="flex gap-2 items-center justify-center"
|
||||
|
||||
@@ -14,10 +14,9 @@ import {
|
||||
NOTIN,
|
||||
} from "@polkadot-api/react-builder"
|
||||
import { Twox128 } from "@polkadot-api/substrate-bindings"
|
||||
import { toHex } from "@polkadot-api/utils"
|
||||
import { fromHex, toHex } from "polkadot-api/utils"
|
||||
import { state, useStateObservable, withDefault } from "@react-rxjs/core"
|
||||
import { createSignal } from "@react-rxjs/utils"
|
||||
import { Binary } from "polkadot-api"
|
||||
import { FC } from "react"
|
||||
import {
|
||||
combineLatest,
|
||||
@@ -78,11 +77,13 @@ export const StorageQuery: FC = () => {
|
||||
const hash$ = single
|
||||
? chainClient$.pipe(
|
||||
switchMap(({ chainHead }) =>
|
||||
chainHead.storage$(hash, "hash", (ctx) =>
|
||||
ctx.dynamicBuilder
|
||||
.buildStorage(entry!.pallet, entry!.entry)
|
||||
.keys.enc(...args),
|
||||
),
|
||||
chainHead
|
||||
.storage$(hash, "hash", (ctx) =>
|
||||
ctx.dynamicBuilder
|
||||
.buildStorage(entry!.pallet, entry!.entry)
|
||||
.keys.enc(...args),
|
||||
)
|
||||
.pipe(map(({ value }) => value)),
|
||||
),
|
||||
)
|
||||
: of(null)
|
||||
@@ -366,7 +367,7 @@ const StorageKeyInput: FC<{
|
||||
<BinaryEditButton
|
||||
initialValue={
|
||||
typeof binaryValue === "string"
|
||||
? Binary.fromHex(binaryValue).asBytes()
|
||||
? fromHex(binaryValue)
|
||||
: (binaryValue ?? undefined)
|
||||
}
|
||||
onValueChange={(value) => setKeyValue({ idx, value })}
|
||||
@@ -441,7 +442,7 @@ export const KeyDisplay: FC = () => {
|
||||
</div>
|
||||
<CopyText text={key ?? ""} disabled={key === null} binary />
|
||||
<BinaryEditButton
|
||||
initialValue={key ? Binary.fromHex(key).asBytes() : undefined}
|
||||
initialValue={key ? fromHex(key) : undefined}
|
||||
onValueChange={(value: NonNullable<DecodedKey>) => {
|
||||
let newKeysEnabled = keysEnabled
|
||||
if (
|
||||
@@ -518,9 +519,7 @@ const decodeKey = (
|
||||
? []
|
||||
: item.type.value.hashers.map((x) => hashersToLength[x.tag])
|
||||
|
||||
let argsRemaining = Binary.fromHex(
|
||||
keyRemaining.replace(twoxHash(item.name), "0x"),
|
||||
).asBytes()
|
||||
let argsRemaining = fromHex(keyRemaining.replace(twoxHash(item.name), "0x"))
|
||||
|
||||
const args: any[] = []
|
||||
const argsLen = codec.args.inner.length
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Chopsticks } from "@/components/Icons"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { chainClient$, client$, lookup$ } from "@/state/chains/chain.state"
|
||||
import { getTypeComplexity } from "@/utils"
|
||||
import { fromHex, toHex } from "@polkadot-api/utils"
|
||||
import { fromHex, toHex } from "polkadot-api/utils"
|
||||
import { state, useStateObservable } from "@react-rxjs/core"
|
||||
import { createSignal } from "@react-rxjs/utils"
|
||||
import { FC, useState } from "react"
|
||||
@@ -31,7 +31,7 @@ const currentValue$ = state(
|
||||
),
|
||||
withLatestFrom(lookup$, selectedEntry$.pipe(filter((v) => v != null))),
|
||||
map(([v, lookup, entry]) => {
|
||||
if (v != null) return v
|
||||
if (v != null) return v.value
|
||||
const pallet = lookup.metadata.pallets.find(
|
||||
(p) => p.name == entry.pallet,
|
||||
)!
|
||||
|
||||
@@ -17,7 +17,7 @@ import { CodecComponentType, NOTIN } from "@polkadot-api/react-builder"
|
||||
import { Button } from "@polkahub/ui-components"
|
||||
import { useStateObservable } from "@react-rxjs/core"
|
||||
import { ChevronLeft, ChevronRight, StopCircle, Trash2 } from "lucide-react"
|
||||
import { Binary, Enum } from "polkadot-api"
|
||||
import { Enum } from "polkadot-api"
|
||||
import { FC, MouseEvent, ReactNode, useMemo, useState } from "react"
|
||||
import { Virtuoso } from "react-virtuoso"
|
||||
import { BlockState } from "../Explorer/block.state"
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
storageSubscriptionKeys$,
|
||||
StorageSubscriptionValue,
|
||||
} from "./storage.state"
|
||||
import { fromHex } from "polkadot-api/utils"
|
||||
|
||||
export const StorageSubscriptions: FC = () => {
|
||||
const keys = useStateObservable(storageSubscriptionKeys$)
|
||||
@@ -460,7 +461,7 @@ const KeyDisplay: FC<{
|
||||
}> = ({ value, keyCodec }) => {
|
||||
const binaryValue = (() => {
|
||||
try {
|
||||
return keyCodec ? Binary.fromHex(keyCodec.enc(...value)).asBytes() : null
|
||||
return keyCodec ? fromHex(keyCodec.enc(...value)) : null
|
||||
} catch (_) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
partitionByKey,
|
||||
toKeySet,
|
||||
} from "@react-rxjs/utils"
|
||||
import { Binary, Enum, HexString } from "polkadot-api"
|
||||
import { Enum, HexString } from "polkadot-api"
|
||||
import {
|
||||
catchError,
|
||||
combineLatest,
|
||||
@@ -416,10 +416,7 @@ export const storageSubscription$ = state(
|
||||
|
||||
export const stringifyArg = (value: unknown) => {
|
||||
if (typeof value === "object" && value !== null) {
|
||||
if (value instanceof Binary) {
|
||||
return bytesToString(value)
|
||||
}
|
||||
return "arg"
|
||||
return value instanceof Uint8Array ? bytesToString(value) : "arg"
|
||||
}
|
||||
return String(value)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { TxBroadcastEvent } from "polkadot-api"
|
||||
import * as React from "react"
|
||||
import { dismissTransaction, onGoingEvents } from "./transactions.state"
|
||||
import { Trash2 } from "lucide-react"
|
||||
import { jsonPrint } from "@polkadot-api/utils"
|
||||
import { jsonSerialize } from "polkadot-api/utils"
|
||||
|
||||
export const Transaction: React.FC<{
|
||||
event:
|
||||
@@ -23,7 +23,11 @@ export const Transaction: React.FC<{
|
||||
case "error":
|
||||
return <span>There was an unexpected error.</span>
|
||||
case "invalid":
|
||||
return <span>Invalid transaction. {jsonPrint(event.value)}</span>
|
||||
return (
|
||||
<span>
|
||||
Invalid transaction. {JSON.stringify(event.value, jsonSerialize)}
|
||||
</span>
|
||||
)
|
||||
case "txBestBlocksState": {
|
||||
return event.found ? (
|
||||
<span>
|
||||
@@ -58,7 +62,7 @@ export const Transaction: React.FC<{
|
||||
</Link>
|
||||
{event.ok
|
||||
? "."
|
||||
: `, but it failed: ${jsonPrint(event.dispatchError)}.`}
|
||||
: `, but it failed: ${JSON.stringify(event.dispatchError, jsonSerialize)}.`}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -6,13 +6,12 @@ import {
|
||||
mergeWithKey,
|
||||
partitionByKey,
|
||||
} from "@react-rxjs/utils"
|
||||
import { HexString, InvalidTxError, TxBroadcastEvent } from "polkadot-api"
|
||||
import { InvalidTxError } from "polkadot-api"
|
||||
import {
|
||||
catchError,
|
||||
filter,
|
||||
merge,
|
||||
mergeMap,
|
||||
Observable,
|
||||
of,
|
||||
skip,
|
||||
takeUntil,
|
||||
@@ -20,8 +19,8 @@ import {
|
||||
withLatestFrom,
|
||||
} from "rxjs"
|
||||
|
||||
const [signedTx$, trackSignedTx] = createSignal<HexString>()
|
||||
const [unsignedTx$, trackUnsignedTx] = createSignal<HexString>()
|
||||
const [signedTx$, trackSignedTx] = createSignal<Uint8Array>()
|
||||
const [unsignedTx$, trackUnsignedTx] = createSignal<Uint8Array>()
|
||||
export { trackSignedTx, trackUnsignedTx }
|
||||
|
||||
export const [dismissTransaction$, dismissTransaction] = createSignal<string>()
|
||||
@@ -29,14 +28,8 @@ export const [dismissTransaction$, dismissTransaction] = createSignal<string>()
|
||||
const transactions$ = mergeWithKey({ signedTx$, unsignedTx$ }).pipe(
|
||||
withLatestFrom(chainClient$),
|
||||
mergeMap(([tx, { client }]) => {
|
||||
const submitAndWatch = client.submitAndWatch as (
|
||||
tx: HexString,
|
||||
at: string,
|
||||
withSigned?: boolean,
|
||||
) => Observable<TxBroadcastEvent>
|
||||
|
||||
let txHash: string = ""
|
||||
return submitAndWatch(tx.payload, "finalized", true).pipe(
|
||||
return client.submitAndWatch(tx.payload, "finalized").pipe(
|
||||
tap((e) => {
|
||||
txHash = e.txHash
|
||||
}),
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
chopsticksInstance$,
|
||||
createChopsticksProvider,
|
||||
} from "@/chopsticks/chopsticks"
|
||||
import { createChopsticksProvider } from "@/chopsticks/chopsticks"
|
||||
import { getHashParams, setHashParams } from "@/hashParams"
|
||||
import { getDynamicBuilder, getLookupFn } from "@polkadot-api/metadata-builders"
|
||||
import {
|
||||
@@ -10,7 +7,7 @@ import {
|
||||
unifyMetadata,
|
||||
} from "@polkadot-api/substrate-bindings"
|
||||
import { getExtrinsicDecoder } from "@polkadot-api/tx-utils"
|
||||
import { fromHex, toHex } from "@polkadot-api/utils"
|
||||
import { fromHex, toHex } from "polkadot-api/utils"
|
||||
import { liftSuspense, sinkSuspense, state, SUSPENSE } from "@react-rxjs/core"
|
||||
import { createSignal } from "@react-rxjs/utils"
|
||||
import { get, update } from "idb-keyval"
|
||||
@@ -75,9 +72,6 @@ console.log("You can enable JSON-RPC logs by calling `setRpcLogsEnabled(true)`")
|
||||
;(window as any).setRpcLogsEnabled = setRpcLogsEnabled
|
||||
|
||||
export const getProvider = (source: ChainSource) => {
|
||||
// TODO bug: provider is not getting disconnected
|
||||
chopsticksInstance$.next(null)
|
||||
|
||||
const provider =
|
||||
source.type === "websocket"
|
||||
? source.withChopsticks
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { chainSpec } from "polkadot-api/chains/ksmcc3"
|
||||
export { chainSpec } from "polkadot-api/chains/kusama"
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { chainSpec } from "polkadot-api/chains/ksmcc3_asset_hub"
|
||||
export { chainSpec } from "polkadot-api/chains/kusama_asset_hub"
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { chainSpec } from "polkadot-api/chains/ksmcc3_coretime"
|
||||
export { chainSpec } from "polkadot-api/chains/kusama_coretime"
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { chainSpec } from "polkadot-api/chains/ksmcc3_encointer"
|
||||
export { chainSpec } from "polkadot-api/chains/kusama_encointer"
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { chainSpec } from "polkadot-api/chains/ksmcc3_people"
|
||||
export { chainSpec } from "polkadot-api/chains/kusama_people"
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { chainSpec } from "polkadot-api/chains/westend2"
|
||||
export { chainSpec } from "polkadot-api/chains/westend"
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { chainSpec } from "polkadot-api/chains/westend2_asset_hub"
|
||||
export { chainSpec } from "polkadot-api/chains/westend_asset_hub"
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { chainSpec } from "polkadot-api/chains/westend2_collectives"
|
||||
export { chainSpec } from "polkadot-api/chains/westend_collectives"
|
||||
|
||||
@@ -1 +1 @@
|
||||
export { chainSpec } from "polkadot-api/chains/westend2_people"
|
||||
export { chainSpec } from "polkadot-api/chains/westend_people"
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import type { JsonRpcProvider } from "polkadot-api"
|
||||
import { getSmProvider } from "polkadot-api/sm-provider"
|
||||
import { Chain } from "polkadot-api/smoldot"
|
||||
import { startFromWorker } from "polkadot-api/smoldot/from-worker"
|
||||
import SmWorker from "polkadot-api/smoldot/worker?worker"
|
||||
import type { JsonRpcProvider } from "polkadot-api/ws-provider/web"
|
||||
|
||||
const [dotChainSpec, ksmChainSpec, paseoChainSpec, westendChainSpec] = [
|
||||
import("polkadot-api/chains/polkadot"),
|
||||
import("polkadot-api/chains/ksmcc3"),
|
||||
import("polkadot-api/chains/kusama"),
|
||||
import("polkadot-api/chains/paseo"),
|
||||
import("polkadot-api/chains/westend2"),
|
||||
import("polkadot-api/chains/westend"),
|
||||
].map((x) => x.then((y) => y.chainSpec))
|
||||
const smoldot = startFromWorker(new SmWorker(), {
|
||||
logCallback: (level, target, message) => {
|
||||
@@ -20,22 +19,12 @@ const smoldot = startFromWorker(new SmWorker(), {
|
||||
},
|
||||
forbidWs: true,
|
||||
})
|
||||
const relayChains: Record<
|
||||
string,
|
||||
{ chainSpec: Promise<string>; chain: Promise<Chain> | null }
|
||||
> = {
|
||||
polkadot: { chainSpec: dotChainSpec, chain: null },
|
||||
kusama: { chainSpec: ksmChainSpec, chain: null },
|
||||
paseo: { chainSpec: paseoChainSpec, chain: null },
|
||||
westend: { chainSpec: westendChainSpec, chain: null },
|
||||
}
|
||||
const getRelayChain = async (name: string) => {
|
||||
if (!relayChains[name].chain) {
|
||||
relayChains[name].chain = smoldot.addChain({
|
||||
chainSpec: await relayChains[name].chainSpec,
|
||||
})
|
||||
}
|
||||
return relayChains[name].chain
|
||||
|
||||
const relayChains: Record<string, Promise<string>> = {
|
||||
polkadot: dotChainSpec,
|
||||
kusama: ksmChainSpec,
|
||||
paseo: paseoChainSpec,
|
||||
westend: westendChainSpec,
|
||||
}
|
||||
|
||||
export interface SmoldotSource {
|
||||
@@ -52,11 +41,12 @@ export async function createSmoldotSource(
|
||||
relayChain?: string,
|
||||
): Promise<SmoldotSource> {
|
||||
if (id in relayChains) {
|
||||
return relayChains[id].chainSpec.then((chainSpec) => ({
|
||||
const chainSpec = await relayChains[id]
|
||||
return {
|
||||
id,
|
||||
type: "chainSpec",
|
||||
value: { chainSpec },
|
||||
}))
|
||||
}
|
||||
}
|
||||
const { chainSpec } = await import(`./chainspecs/${id}.ts`)
|
||||
const parsed = JSON.parse(chainSpec)
|
||||
@@ -71,16 +61,15 @@ export async function createSmoldotSource(
|
||||
}
|
||||
|
||||
export function getSmoldotProvider(source: SmoldotSource): JsonRpcProvider {
|
||||
const chain = source.value.relayChain
|
||||
? getRelayChain(source.value.relayChain).then((chain) =>
|
||||
smoldot.addChain({
|
||||
chainSpec: source.value.chainSpec,
|
||||
potentialRelayChains: [chain],
|
||||
}),
|
||||
)
|
||||
: smoldot.addChain({
|
||||
chainSpec: source.value.chainSpec,
|
||||
})
|
||||
const chainFactory = () =>
|
||||
source.value.relayChain
|
||||
? relayChains[source.value.relayChain].then(async (chainSpec) =>
|
||||
smoldot.addChain({
|
||||
chainSpec: source.value.chainSpec,
|
||||
potentialRelayChains: [await smoldot.addChain({ chainSpec })],
|
||||
}),
|
||||
)
|
||||
: smoldot.addChain({ chainSpec: source.value.chainSpec })
|
||||
|
||||
return getSmProvider(chain)
|
||||
return getSmProvider(chainFactory)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { withPolkadotSdkCompat } from "polkadot-api/polkadot-sdk-compat"
|
||||
import { getWsProvider, JsonRpcProvider } from "polkadot-api/ws-provider"
|
||||
import type { JsonRpcProvider } from "polkadot-api"
|
||||
import { getWsProvider } from "polkadot-api/ws"
|
||||
|
||||
export interface WebsocketSource {
|
||||
type: "websocket"
|
||||
@@ -17,5 +17,5 @@ export async function createWebsocketSource(
|
||||
}
|
||||
|
||||
export function getWebsocketProvider(source: WebsocketSource): JsonRpcProvider {
|
||||
return withPolkadotSdkCompat(getWsProvider(source.endpoint))
|
||||
return getWsProvider(source.endpoint)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import { state } from "@react-rxjs/core"
|
||||
import { Binary, createClient, SS58String } from "polkadot-api"
|
||||
import { catchError, from, of, tap } from "rxjs"
|
||||
import { getProvider } from "./chains/chain.state"
|
||||
import { fromHex } from "polkadot-api/utils"
|
||||
|
||||
export interface Identity {
|
||||
displayName: string
|
||||
@@ -51,14 +52,16 @@ export const getAddressName = async (
|
||||
if (!id) {
|
||||
const sup = await typedApi.query.Identity.SuperOf.getValue(addr)
|
||||
if (!sup) return null
|
||||
const subDisplay = readIdentityData(sup[1])?.asText() || ""
|
||||
const supData = readIdentityData(sup[1])
|
||||
const subDisplay = supData && Binary.toText(supData)
|
||||
if (!subDisplay) return null
|
||||
subIdStr = ` (${subDisplay})`
|
||||
id = await typedApi.query.Identity.IdentityOf.getValue(sup[0])
|
||||
if (!id) return null
|
||||
}
|
||||
|
||||
const displayName = readIdentityData(id.info.display)?.asText()
|
||||
const displayData = readIdentityData(id.info.display)
|
||||
const displayName = displayData && Binary.toText(displayData)
|
||||
return displayName
|
||||
? {
|
||||
displayName: `${displayName}${subIdStr}`,
|
||||
@@ -88,9 +91,8 @@ export const identity$ = state(
|
||||
(address) => cache.getValue()[address] ?? null,
|
||||
)
|
||||
|
||||
const readIdentityData = (identityData: IdentityData): Binary | null => {
|
||||
const readIdentityData = (identityData: IdentityData): Uint8Array | null => {
|
||||
if (identityData.type === "None" || identityData.type === "Raw0") return null
|
||||
if (identityData.type === "Raw1")
|
||||
return Binary.fromBytes(new Uint8Array(identityData.value))
|
||||
return identityData.value
|
||||
if (identityData.type === "Raw1") return new Uint8Array(identityData.value)
|
||||
return fromHex(identityData.value)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user