diff --git a/src/git/git.ts b/src/git/git.ts index 7c35e28..735dc0c 100644 --- a/src/git/git.ts +++ b/src/git/git.ts @@ -169,7 +169,7 @@ class Git { let data = GitUtils.encodeObject(sha) let path = this.objectPath(sha) log("writing...", path, sha) - let status = await this.storage.upload(path, data, this.remoteName, this.remoteUrl) + let status = await this.storage.upload(path, data) log("status", status) } diff --git a/src/index.ts b/src/index.ts index 200ac9e..8a9a6ba 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ import GitRemoteHelper from './git/git-remote-helper' import { ApiBaseParams } from './git/git-remote-helper' import Git from './git/git' import { log } from './git/log' -import { MockStorage } from './storage/MockStorage' +import { ETHStorage } from './storage/ETHStorage' let git: Git; GitRemoteHelper({ @@ -15,7 +15,7 @@ GitRemoteHelper({ * This will always be invoked when the remote helper is invoked */ init: async (p: ApiBaseParams) => { - git = new Git(p, new MockStorage(p.remoteUrl)) + git = new Git(p, new ETHStorage(p.remoteUrl)) return }, /** diff --git a/src/storage/ETHStorage.ts b/src/storage/ETHStorage.ts index ca7cfb5..01755d4 100644 --- a/src/storage/ETHStorage.ts +++ b/src/storage/ETHStorage.ts @@ -1,5 +1,5 @@ import { Ref, Status, Storage } from "./storage" - +import { callContractMethod } from "../wallet/index" export class ETHStorage implements Storage { repoURI: string @@ -7,23 +7,52 @@ export class ETHStorage implements Storage { constructor(repoURI: string) { this.repoURI = repoURI } - download(path: string): Promise<[Status, Buffer]> { - throw new Error("Method not implemented.") + + async download(path: string): Promise<[Status, Buffer]> { + const buffer = await callContractMethod({ + method: 'download', + path, + file: null, + sha: null + }) + return [Status.SUCCEED, buffer] } - upload(path: string, file: Buffer): Promise { - throw new Error("Method not implemented.") + + async upload(path: string, file: Buffer): Promise { + await callContractMethod({ + method: 'upload', + path, + file, + sha: null + }) + return Status.SUCCEED } + remove(path: string): Promise { throw new Error("Method not implemented.") } - listRefs(): Promise { - throw new Error("Method not implemented.") + + async listRefs(): Promise { + const result = await callContractMethod({ + method: 'listRefs', + path: null, + file: null, + sha: null + }) + return result } - setRef(path: string, sha: string): Promise { - throw new Error("Method not implemented.") + + async setRef(path: string, sha: string): Promise { + await callContractMethod({ + method: 'setRef', + path, + file: null, + sha + }) + return Status.SUCCEED } + removeRef(path: string): Promise { throw new Error("Method not implemented.") } - } diff --git a/src/storage/MockStorage.ts b/src/storage/MockStorage.ts index 6dd6edf..a5106e6 100644 --- a/src/storage/MockStorage.ts +++ b/src/storage/MockStorage.ts @@ -29,8 +29,8 @@ export class MockStorage implements Storage { catch (e) { return [] } - } + async setRef(path: string, sha: string): Promise { let dict let stPath = join(mockPath, "refs.json") @@ -47,6 +47,7 @@ export class MockStorage implements Storage { await fs.writeFile(stPath, JSON.stringify(dict)) return Status.SUCCEED } + async removeRef(path: string): Promise { let stPath = join(mockPath, "refs.json") let refsJson = await fs.readFile(stPath) @@ -59,12 +60,12 @@ export class MockStorage implements Storage { async remove(path: string): Promise { throw new Error("Method not implemented.") } + async download(path: string): Promise<[Status, Buffer]> { let buffer = await fs.readFile(join(mockPath, path)) return [Status.SUCCEED, buffer] } - async upload(path: string, file: Buffer): Promise { let stPath = join(mockPath, path) await fs.mkdir(pathUtil.dirname(stPath), { recursive: true }) diff --git a/src/storage/storage.ts b/src/storage/storage.ts index 2f9e8ed..fa58993 100644 --- a/src/storage/storage.ts +++ b/src/storage/storage.ts @@ -15,10 +15,10 @@ export interface Storage { repoURI: string download(path: string): Promise<[Status, Buffer]> - upload(path: string, file: Buffer, remoteName: string, remoteUrl: string): Promise + upload(path: string, file: Buffer): Promise remove(path: string): Promise listRefs(): Promise setRef(path: string, sha: string): Promise removeRef(path: string): Promise -} \ No newline at end of file +} diff --git a/src/wallet/abi.js b/src/wallet/abi.js new file mode 100644 index 0000000..9dfbd00 --- /dev/null +++ b/src/wallet/abi.js @@ -0,0 +1,260 @@ +export default [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "countChunks", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "delRef", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "path", + "type": "bytes" + } + ], + "name": "download", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "listRefs", + "outputs": [ + { + "components": [ + { + "internalType": "bytes20", + "name": "hash", + "type": "bytes20" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "internalType": "struct Git3.refData[]", + "name": "list", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "name": "nameToRefInfo", + "outputs": [ + { + "internalType": "bytes20", + "name": "hash", + "type": "bytes20" + }, + { + "internalType": "uint96", + "name": "index", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "refs", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "val", + "type": "uint256" + } + ], + "name": "refund", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "refund1", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "path", + "type": "bytes" + } + ], + "name": "remove", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "bytes20", + "name": "refHash", + "type": "bytes20" + } + ], + "name": "setRef", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "name", + "type": "bytes" + } + ], + "name": "size", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "storageManager", + "outputs": [ + { + "internalType": "contract IFileOperator", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "path", + "type": "bytes" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upload", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "path", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "chunkId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "uploadChunk", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] \ No newline at end of file diff --git a/src/wallet/index.html b/src/wallet/index.html new file mode 100644 index 0000000..ad96b67 --- /dev/null +++ b/src/wallet/index.html @@ -0,0 +1,5 @@ + + + "git3://" web3 git protocol, code for the open web + + diff --git a/src/wallet/index.js b/src/wallet/index.js new file mode 100644 index 0000000..bbe5ecd --- /dev/null +++ b/src/wallet/index.js @@ -0,0 +1,67 @@ +import { mkdirSync, readFileSync, existsSync, statSync } from "fs" +import { ethers } from 'ethers' +import parse from 'parse-git-config' +import abi from './abi.js' + +// path -> /ab/123ab3123 +export async function callContractMethod ({ + method = 'upload', + path, + file, + sha +}) { + const wallet = 'default' + const keyPath = process.env.HOME + "/.git3/keys" + mkdirSync(keyPath, { recursive: true }) + + const content = readFileSync(`${keyPath}/${wallet}`).toString() + const [walletType, key] = content.split('\n') + const provider = new ethers.providers.JsonRpcProvider('https://galileo.web3q.io:8545'); + + let etherWallet = walletType === 'privateKey' + ? new ethers.Wallet(key) + : ethers.Wallet.fromMnemonic(key) + + etherWallet = etherWallet.connect(provider) + const contract = new ethers.Contract('0x680336910D9357F6aDf26c0d61eAB8e65998Ab2d', abi, etherWallet); + const pathBuffer = path ? Buffer.from(path) : '' + + if (method === 'upload') { + await contract.upload(pathBuffer, file) + } + + if (method === 'download') { + const res = await contract.download(pathBuffer) + const buf = Buffer.from(res[0].slice(2), 'hex') + return buf + } + + if (method === 'setRef') { + const res = await contract.setRef(path, '0x' + sha) + } + + if (method === 'listRefs') { + const res = await contract.listRefs() + const refs = res.map(i => ({ + ref: i[1], + sha: i[0].slice(2) + })) + return refs + } +} + +// callContractMethod('kai', 'upload', '/07/549ed56229550960d2cb32b086df52304d9a86') +// callContractMethod('kai', 'download', '/07/549ed56229550960d2cb32b086df52304d9a86') +// callContractMethod({ +// wallet: 'kai', +// method: 'setRef', +// path: '/refs/heads/master', +// sha: '07549ed56229550960d2cb32b086df52304d9a86' +// }) + +callContractMethod({ + wallet: 'kai', + method: 'listRefs', + // path: '/refs/heads/master', + // sha: '07549ed56229550960d2cb32b086df52304d9a86' +}) \ No newline at end of file diff --git a/src/wallet/index.ts b/src/wallet/index.ts deleted file mode 100644 index f31a4a8..0000000 --- a/src/wallet/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -// program stomach view picnic because depth ready sight appear spin cream prefer -// selfAddress = 0xd1a98cD2382B8DA25280B380C0b9D85A63aD2818 -// contractAddress = '0x2A9B264471b19bAB5faD04807328F0dd4FD5549c' -import { ethers } from "ethers" -import uploader from './uploader.js' - -const mnemonic = 'program stomach view picnic because depth ready sight appear spin cream prefer' -const wallet = ethers.Wallet.fromMnemonic(mnemonic) -const contractAddress = '0x2A9B264471b19bAB5faD04807328F0dd4FD5549c' - -async function run () { - const addr = await wallet.getAddress() - console.log(addr) - - try { - const res = await uploader.deploy('/Users/kai/Code/git-remote-git3/src/wallet/git', contractAddress, wallet.privateKey) - console.log(res) - } catch (error) { - console.log(error) - } -} - -run() \ No newline at end of file