Skip to content

Commit

Permalink
feat: dweb support (#114)
Browse files Browse the repository at this point in the history
  • Loading branch information
fmorency authored Sep 21, 2023
1 parent 11faaf9 commit 447c645
Show file tree
Hide file tree
Showing 22 changed files with 396 additions and 134 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ workflows:
node_version:
- 'lts'
- 'current'
- '16.16.0'
- '16.20.2'
- create:
release_id: "${CIRCLE_PR_NUMBER}"

Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
16.16.0
16.20.2
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@liftedinit/many-js",
"version": "0.1.0-alpha.12",
"version": "0.1.0-alpha.13",
"homepage": "https://github.com/liftedinit/many-js",
"main": "dist/index.js",
"files": [
Expand Down
7 changes: 7 additions & 0 deletions src/const.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { EventType, EventTypeIndices } from "./network/modules/types"

export const HIGH_WATER_MARK = 5242880 // 5MB

export const ONE_SECOND = 1000
export const ONE_MINUTE = 60 * ONE_SECOND

export const eventTypeNameToIndices: {
[key in EventType]: EventTypeIndices
} = {
[EventType.send]: [6, 0],
[EventType.kvstorePut]: [7, 0],
[EventType.kvstoreDisable]: [7, 1],
[EventType.accountCreate]: [9, 0],
[EventType.accountSetDescription]: [9, 1],
[EventType.accountAddRoles]: [9, 2],
Expand All @@ -22,4 +26,7 @@ export const eventTypeNameToIndices: {
[EventType.accountMultisigExpired]: [9, [1, 6]],
[EventType.mint]: [12, 0],
[EventType.burn]: [12, 1],
[EventType.kvstoreTransfer]: [13, 0],
[EventType.webDeploy]: [17, 0],
[EventType.webRemove]: [17, 1],
}
6 changes: 6 additions & 0 deletions src/identity/address.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import base32Decode from "base32-decode"
import base32Encode from "base32-encode"
import crc from "crc"
import { Tagged } from "cbor"

export const ANON_IDENTITY = "maa"
export const ILLEGAL_IDENTITY = "maiyg"
Expand Down Expand Up @@ -96,4 +97,9 @@ export class Address {
])
return new Address(Buffer.concat([bytes, subresourceBytes]))
}

encodeCBOR(encoder: any) {
const tagged = new Tagged(10000, Buffer.from(this.bytes))
return encoder.pushAny(tagged)
}
}
36 changes: 24 additions & 12 deletions src/message/cose.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
} from "../identity"
import { Message } from "../message"
import { CborData, CborMap, tag } from "./cbor"
import { HIGH_WATER_MARK } from "../const"

export const ANONYMOUS = Buffer.from([0x00])
export const EMPTY = Buffer.alloc(0)
Expand Down Expand Up @@ -61,13 +62,15 @@ export class CoseMessage {
const protectedHeader = await this.getProtectedHeader(identity)
const cborProtectedHeader = cbor.encodeCanonical(protectedHeader)
const content = message.getContent()
const cborContent = cbor.encode(tag(10001, content))
const toBeSigned = cbor.encodeCanonical([
"Signature1",
cborProtectedHeader,
EMPTY,
cborContent,
])
const cborContent = cbor.encodeOne(tag(10001, content), {
highWaterMark: HIGH_WATER_MARK,
} as Object)

const toBeSigned = cbor.encodeOne(
["Signature1", cborProtectedHeader, EMPTY, cborContent],
{ highWaterMark: HIGH_WATER_MARK } as Object,
)

const unprotectedHeader = await identity.getUnprotectedHeader(
cborContent,
cborProtectedHeader,
Expand Down Expand Up @@ -116,11 +119,19 @@ export class CoseMessage {
}

toCborData(): CborData {
const p = cbor.encodeCanonical(this.protectedHeader)
const u = this.unprotectedHeader
const payload = cbor.encode(tag(10001, this.content))
let sig = this.signature
return cbor.encodeCanonical(tag(18, [p, u, payload, sig]))
const payload = cbor.encodeOne(tag(10001, this.content), {
highWaterMark: HIGH_WATER_MARK,
} as Object)
const protectedHeader = cbor.encodeOne(this.protectedHeader)
return cbor.encodeOne(
tag(18, [
protectedHeader,
this.unprotectedHeader,
payload,
this.signature,
]),
{ highWaterMark: HIGH_WATER_MARK } as Object,
)
}

toString(): string {
Expand Down Expand Up @@ -164,6 +175,7 @@ export class CoseKey {
}

toCborData(): CborData {
// encodeCanonical will encode the map in sorted order
return cbor.encodeCanonical([this.key])
}

Expand Down
79 changes: 42 additions & 37 deletions src/message/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import cbor from "cbor";
import cbor from "cbor"
import { Address, Identity } from "../identity"
import { CborData, CborMap, tag } from "./cbor";
import { CoseMessage, decoders } from "./cose";
import { ManyError, SerializedManyError } from "./error";
import { CborData, CborMap, tag } from "./cbor"
import { CoseMessage, decoders } from "./cose"
import { ManyError, SerializedManyError } from "./error"
import { Attributes, AsyncAttribute } from "./attributes"
import { HIGH_WATER_MARK } from "../const"

interface MessageContent {
version?: number;
version?: number
from?: Address
to?: Address
method: string;
data?: any;
timestamp?: number;
id?: number;
nonce?: string;
attrs?: string[];
method: string
data?: any
timestamp?: number
id?: number
nonce?: string
attrs?: string[]
}

export class Message {
Expand All @@ -40,65 +41,69 @@ export class Message {

static fromObject(obj: MessageContent): Message {
if (!obj.method) {
throw new Error("Property 'method' is required.");
throw new Error("Property 'method' is required.")
}
const content = new Map();
content.set(0, obj.version ? obj.version : 1);
const content = new Map()
if (obj.from) {
content.set(1, obj.from.toString());
content.set(1, obj.from)
}
if (obj.to) {
content.set(2, obj.to.toString());
content.set(2, obj.to)
}
content.set(3, obj.method);
content.set(3, obj.method)
if (obj.data) {
content.set(4, cbor.encode(obj.data));
content.set(
4,
cbor.encodeOne(obj.data, {
highWaterMark: HIGH_WATER_MARK,
} as Object),
)
}
content.set(
5,
tag(1, obj.timestamp ? obj.timestamp : Math.floor(Date.now() / 1000))
);
tag(1, obj.timestamp ? obj.timestamp : Math.floor(Date.now() / 1000)),
)
if (obj.id) {
content.set(6, obj.id);
content.set(6, obj.id)
}
if (obj.nonce) {
content.set(7, cbor.encode(obj.nonce))
}
if (obj.attrs) {
content.set(8, obj.attrs);
content.set(8, obj.attrs)
}
return new Message(content);
return new Message(content)
}

static fromCoseMessage(message: CoseMessage): Message {
const content = message.content;
const data = content.get(4);
const content = message.content
const data = content.get(4)
if (typeof data == "object" && !Buffer.isBuffer(data)) {
throw new ManyError(
Object.fromEntries(data.entries()) as SerializedManyError
);
Object.fromEntries(data.entries()) as SerializedManyError,
)
}
return new Message(content);
return new Message(content)
}

static fromCborData(data: CborData): Message {
const cose = CoseMessage.fromCborData(data);
return Message.fromCoseMessage(cose);
const cose = CoseMessage.fromCborData(data)
return Message.fromCoseMessage(cose)
}

private replacer(key: string, value: any) {
if (value?.type === "Buffer") {
return Buffer.from(value.data).toString("hex");
return Buffer.from(value.data).toString("hex")
} else if (value instanceof Map) {
return Object.fromEntries(value.entries());
return Object.fromEntries(value.entries())
} else if (typeof value === "bigint") {
return parseInt(value.toString());
return parseInt(value.toString())
} else if (key === "hash") {
return Buffer.from(value).toString("hex");
return Buffer.from(value).toString("hex")
} else if (key === "bytes") {
return Buffer.from(value).toString("hex");
return Buffer.from(value).toString("hex")
} else {
return value;
return value
}
}

Expand All @@ -111,6 +116,6 @@ export class Message {
}

toString() {
return JSON.stringify(this.content, this.replacer, 2);
return JSON.stringify(this.content, this.replacer, 2)
}
}
4 changes: 2 additions & 2 deletions src/network/modules/account/__tests__/account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe("Account", () => {
roles.set(identityStr3, [AccountRole.canMultisigApprove])
const _roles = Array.from(roles).reduce((acc, rolesForAddress) => {
const [address, roleList] = rolesForAddress
const taggedIdentity = tag(10000, Address.fromString(address).toBuffer())
const taggedIdentity = Address.fromString(address)
acc.set(taggedIdentity, roleList)
return acc
}, new Map())
Expand Down Expand Up @@ -346,7 +346,7 @@ function makeMultisigInfoResponse({
amount: 2,
}),
)
const submitter = tag(10000, Address2)
const submitter = Address2
const approvers = new Map().set(submitter, new Map().set(0, true))
const threshold = 2
const executeAutomatically = false
Expand Down
16 changes: 8 additions & 8 deletions src/network/modules/events/__tests__/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ function makeMultisigSubmitTxnResponse({
}) {
const m = new Map()
m.set(0, txnTypeIndices)
.set(1, tag(10000, Address.fromString(submitter).toBuffer()))
.set(2, tag(10000, Address.fromString(accountSource).toBuffer()))
.set(1, Address.fromString(submitter))
.set(2, Address.fromString(accountSource))
.set(4, submittedTxn)
.set(5, token)
.set(6, threshold)
Expand Down Expand Up @@ -141,7 +141,7 @@ function makeMultisigTxnResponse({
}) {
const m = new Map()
.set(2, token)
.set(3, tag(10000, Address.fromString(actor).toBuffer()))
.set(3, Address.fromString(actor))

return makeTxn({
id,
Expand Down Expand Up @@ -183,9 +183,9 @@ function makeSendTxn({
}) {
const m = new Map()
m.set(0, eventTypeNameToIndices.send)
.set(1, tag(10000, Address.fromString(source).toBuffer()))
.set(2, tag(10000, Address.fromString(destination).toBuffer()))
.set(3, tag(10000, Address.fromString(symbol).toBuffer()))
.set(1, Address.fromString(source))
.set(2, Address.fromString(destination))
.set(3, Address.fromString(symbol))
.set(4, amount)

return makeTxn({ id, time, txnData: m })
Expand Down Expand Up @@ -451,7 +451,7 @@ roles.set(identityStr3, [AccountRole.canMultisigApprove])

const _roles = Array.from(roles).reduce((acc, rolesForAddress) => {
const [address, roleList] = rolesForAddress
const bytes = tag(10000, Address.fromString(address).toBuffer())
const bytes = Address.fromString(address)
acc.set(bytes, roleList)
return acc
}, new Map())
Expand Down Expand Up @@ -579,7 +579,7 @@ function makeAccountTxnResponse({
}) {
let m = new Map()
.set(0, txnTypeIndices)
.set(1, tag(10000, Address.fromString(accountSource).toBuffer()))
.set(1, Address.fromString(accountSource))
m = new Map([...m, ...txnData])
return m
}
1 change: 1 addition & 0 deletions src/network/modules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ export * from "./account"
export * from "./events"
export * from "./base"
export * from "./tokens"
export * from "./web"
8 changes: 4 additions & 4 deletions src/network/modules/kvStore/kvStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,22 +84,22 @@ function makeKVStorePut(param: KVStorePutParam): Map<number, any> {
const data = new Map()
data.set(0, Buffer.from(param.key))
data.set(1, Buffer.from(param.value))
param.owner && data.set(2, tag(10000, param.owner))
param.owner && data.set(2, param.owner)
return data
}

function makeKVStoreDisable(param: KVStoreDisableParam): Map<number, any> {
const data = new Map()
data.set(0, Buffer.from(param.key))
param.owner && data.set(1, tag(10000, param.owner))
param.owner && data.set(1, param.owner)
return data
}

function makeKVStoreTransfer(param: KVStoreTransferParam): Map<number, any> {
const data = new Map()
data.set(0, Buffer.from(param.key))
data.set(2, tag(10000, param.newOwner))
param.owner && data.set(1, tag(10000, param.owner))
data.set(2, param.newOwner)
param.owner && data.set(1, param.owner)
return data
}

Expand Down
8 changes: 1 addition & 7 deletions src/network/modules/kvStore/types.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
import { Address } from "../../../identity"
import { NetworkModule } from "../types"
import { NetworkModule, SortOrder } from "../types"

type KeyFilterType =
| [0, Address] // Owner
| [1, Address] // Previous Owner
| [2, boolean] // Disabled?

export enum SortOrder {
Indeterminate = 0,
Ascending = 1,
Descending = 2,
}

export interface KVStoreInfo {
hash: string
}
Expand Down
Loading

0 comments on commit 447c645

Please sign in to comment.