Skip to content

Commit

Permalink
optional : encrypt + sync
Browse files Browse the repository at this point in the history
  • Loading branch information
wighawag committed Nov 27, 2023
1 parent 15a09e7 commit 5de912c
Show file tree
Hide file tree
Showing 9 changed files with 623 additions and 305 deletions.
18 changes: 18 additions & 0 deletions pnpm-lock.yaml

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

3 changes: 3 additions & 0 deletions web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,16 @@
"wait-on": "^7.2.0"
},
"dependencies": {
"@noble/ciphers": "^0.4.0",
"@scure/base": "^1.1.3",
"@types/lodash-es": "^4.17.12",
"ethereum-indexer-browser": "^0.6.28",
"ethereum-tx-observer": "^0.0.3",
"immer": "^10.0.3",
"jolly-roger-common": "workspace:*",
"jolly-roger-indexer": "workspace:*",
"lodash-es": "^4.17.21",
"lz-string": "^1.5.0",
"named-logs": "^0.2.2",
"radiate": "^0.0.1",
"theme-change": "^2.5.0",
Expand Down
145 changes: 100 additions & 45 deletions web/src/lib/web3/account-data.ts → web/src/lib/account/account-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ import type {EIP1193TransactionWithMetadata} from 'web3-connection';
import type {PendingTransaction, PendingTransactionState} from 'ethereum-tx-observer';
import {initEmitter} from 'radiate';
import {writable} from 'svelte/store';
import {bytesToHex, hexToBytes} from 'viem';
import {AccountDB} from './account-db';
import {AccountDB, type AccountInfo, type SyncInfo, type SyncingState} from './account-db';

export type SendMessageMetadata = {
type: 'message';
Expand Down Expand Up @@ -36,26 +35,17 @@ function fromOnChainActionToPendingTransaction(hash: `0x${string}`, onchainActio
} as PendingTransaction;
}

export function initAccountData() {
export function initAccountData(dbName: string, syncInfo?: SyncInfo) {
const emitter = initEmitter<{name: 'newTx'; txs: PendingTransaction[]} | {name: 'clear'}>();

const $onchainActions: OnChainActions = {};
const onchainActions = writable<OnChainActions>($onchainActions);

let accountDB: AccountDB<AccountData> | undefined;
async function load(info: {
address: `0x${string}`;
chainId: string;
genesisHash: string;
privateSignature: `0x${string}`;
}) {
const key = hexToBytes(info.privateSignature).slice(0, 32);
const data = await _load({
address: info.address,
chainId: info.chainId,
genesisHash: info.genesisHash,
key,
});
let unsubscribeFromSync: (() => void) | undefined;

async function load(info: AccountInfo, remoteSyncEnabled?: boolean) {
const data = await _load(info, remoteSyncEnabled);

for (const hash in data.onchainActions) {
const onchainAction = (data.onchainActions as any)[hash];
Expand All @@ -71,16 +61,6 @@ export function initAccountData() {
const onchainAction = (onChainActions as any)[hash];
const tx = fromOnChainActionToPendingTransaction(hash as `0x${string}`, onchainAction);
pending_transactions.push(tx);
if (onchainAction.revealTx) {
const tx = {
hash: onchainAction.revealTx.hash,
request: onchainAction.revealTx.request,
final: onchainAction.revealTx.final,
inclusion: onchainAction.revealTx.inclusion,
status: onchainAction.revealTx.status,
} as PendingTransaction;
pending_transactions.push(tx);
}
}
emitter.emit({name: 'newTx', txs: pending_transactions});
}
Expand All @@ -89,6 +69,12 @@ export function initAccountData() {
//save before unload
await save();

if (unsubscribeFromSync) {
unsubscribeFromSync();
unsubscribeFromSync = undefined;
}

accountDB?.destroy();
accountDB = undefined;

// delete all
Expand All @@ -106,15 +92,72 @@ export function initAccountData() {
});
}

async function _load(info: {
address: `0x${string}`;
chainId: string;
genesisHash: string;
key: Uint8Array;
}): Promise<AccountData> {
const privateKey = info.key;
accountDB = new AccountDB(info.address, info.chainId, info.genesisHash);
return (await accountDB.load()) || emptyAccountData;
function _merge(
localData?: AccountData,
remoteData?: AccountData,
): {newData: AccountData; newDataOnLocal: boolean; newDataOnRemote: boolean} {
let newDataOnLocal = false;
let newDataOnRemote = false;

let newData: AccountData;
if (!localData) {
newData = {
onchainActions: {},
};
} else {
newData = localData;
}

// hmm check if valid
if (!remoteData || !remoteData.onchainActions) {
remoteData = {
onchainActions: {},
};
}

for (const key of Object.keys(remoteData.onchainActions)) {
const txHash = key as `0x${string}`;
if (!newData.onchainActions[txHash]) {
newData.onchainActions[txHash] = remoteData.onchainActions[txHash];
newDataOnRemote = true;
}
}

for (const key of Object.keys(newData.onchainActions)) {
const txHash = key as `0x${string}`;
if (!remoteData.onchainActions[txHash]) {
newDataOnLocal = true;
break;
}
}

return {
newData,
newDataOnLocal,
newDataOnRemote,
};
}

async function _load(info: AccountInfo, remoteSyncEnabled?: boolean): Promise<AccountData> {
accountDB = new AccountDB(
dbName,
info,
_merge,
syncInfo
? {...syncInfo, enabled: remoteSyncEnabled === undefined ? syncInfo.enabled : remoteSyncEnabled}
: undefined,
);

unsubscribeFromSync = accountDB.subscribe(onSync);
return (await accountDB.requestSync(true)) || emptyAccountData;
}

function onSync(syncingState: SyncingState<AccountData>): void {
// TODO ?
// $onchainActions = syncingState.data?.onchainActions || {};
// onchainActions.set($onchainActions);
// $offchainState = syncingState.data?.offchainState;
// offchainState.set($offchainState);
}

async function _save(accountData: AccountData) {
Expand Down Expand Up @@ -151,27 +194,39 @@ export function initAccountData() {
});
}

function _updateTx(pendingTransaction: PendingTransaction) {
function _updateTx(pendingTransaction: PendingTransaction): boolean {
const action = $onchainActions[pendingTransaction.hash];
if (action) {
action.inclusion = pendingTransaction.inclusion;
action.status = pendingTransaction.status;
action.final = pendingTransaction.final;
if (
action.inclusion !== pendingTransaction.inclusion ||
action.status !== pendingTransaction.status ||
action.final !== pendingTransaction.final
) {
action.inclusion = pendingTransaction.inclusion;
action.status = pendingTransaction.status;
action.final = pendingTransaction.final;
return true;
}
}
return false;
}

function updateTx(pendingTransaction: PendingTransaction) {
_updateTx(pendingTransaction);
onchainActions.set($onchainActions);
save();
if (_updateTx(pendingTransaction)) {
onchainActions.set($onchainActions);
save();
}
}

function updateTxs(pendingTransactions: PendingTransaction[]) {
let anyChanges = false;
for (const p of pendingTransactions) {
_updateTx(p);
anyChanges = anyChanges || _updateTx(p);
}
if (anyChanges) {
onchainActions.set($onchainActions);
save();
}
onchainActions.set($onchainActions);
save();
}

// use with caution
Expand Down

0 comments on commit 5de912c

Please sign in to comment.