Skip to content

Commit

Permalink
Merge pull request #49 from mirrorworld-universe/wsw
Browse files Browse the repository at this point in the history
Add Nisaba service for HSSN to fix:
  • Loading branch information
ZeneDeLuca authored Oct 31, 2024
2 parents 0c55ded + d0a2c87 commit 1ec4622
Show file tree
Hide file tree
Showing 8 changed files with 3,116 additions and 12 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Here is the source code for the Shared Sequencer Network's development version.
Here is the source code for Nisaba service for HSSN.
The online RPC url: https://nisaba-hssn.sonic.game
2 changes: 2 additions & 0 deletions hypergrid-nisaba/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/logs/
/node_modules/
1 change: 1 addition & 0 deletions hypergrid-nisaba/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Here is the source code for the Shared Sequencer Network's development version.
2,895 changes: 2,895 additions & 0 deletions hypergrid-nisaba/package-lock.json

Large diffs are not rendered by default.

12 changes: 12 additions & 0 deletions hypergrid-nisaba/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"dependencies": {
"@aws-sdk/client-dynamodb": "^3.670.0",
"@aws-sdk/lib-dynamodb": "^3.670.0",
"@aws-sdk/util-dynamodb": "^3.670.0",
"@solana/web3.js": "^1.95.4",
"cors": "^2.8.5",
"express": "^4.21.0",
"body-parser": "^1.20.3",
"winston": "^3.15.0"
}
}
199 changes: 199 additions & 0 deletions hypergrid-nisaba/src/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");
const { DynamoDBDocumentClient, GetCommand, PutCommand } = require("@aws-sdk/lib-dynamodb");
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
const crypto = require('crypto')
const winston = require('winston');

const logger = winston.createLogger({
// Log only if level is less than (meaning more severe) or equal to this
level: "info",
// format: winston.format.json(),
defaultMeta: { service: 'user-service' },
// Use timestamp and printf to create a standard log format
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
// winston.format.printf(
// (info) => `${info.timestamp} ${info.level}: ${info.message}`
// )
),
// Log to the console and a file
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: "logs/app.log" }),
],
});

const client = new DynamoDBClient({});
const docClient = DynamoDBDocumentClient.from(client);
const TABLE_NAME = "HypergridStates";
const HSSN_RPC_DEFAULT = "https://exapi.testnet.hssn.sonic.game";

const PORT = process.env.PORT || 3000;
const app = express();
app.use(function(req, res, next) {
res.setHeader("Access-Control-Allow-Methods", "POST, PUT, OPTIONS, DELETE, GET, fetch");
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Credentials", true);
next();
});
app.use(bodyParser.json());
app.use(cors());

async function get_solana_account(rpc, address) {
logger.info("get_solana_account", rpc, address);
const url = rpc;
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
jsonrpc: "2.0",
id: 1,
method: "getAccountInfo",
params: [
address,
{
"encoding": "base64"
}
]
}),
};

try {
let response = await fetch(url, options);
let data = await response.text();
logger.info(response.status, data);
return [response.status, data];
} catch (error) {
logger.error(error);
return [500, {error: error}];
}
}

async function get_hypergrid_node(rpc, address) {
logger.info("get_hypergrid_node", rpc, address);
//get the nodes from cosmos via http request
const url = rpc + "/hypergrid-ssn/hypergridssn/hypergrid_node/" + address;
try {
// let response = await axios.get(url);
let response = await fetch(url);
let data = await response.text();
logger.info(response.status, data);
return [response.status, data];
} catch (error) {
logger.error(error);
return [500, {error: error}];
}
}

async function add_to_db(rpc, address, version, status, data) {
logger.info("add_to_db", rpc, address, version, status, data);
//hash key = rpc + address + version
hashkey = crypto.createHash('sha256').update(rpc + address + version).digest('hex');

const params = {
TableName: TABLE_NAME,
Item: {
hashkey: hashkey,
rpc: rpc,
address: address,
version: version,
status: status,
data: data,
},
};

try {
const response = await docClient.send(new PutCommand(params));
logger.info(response);
} catch (error) {
logger.error(error);
}
}

async function get_from_db(rpc, address, version) {
logger.info("get_from_db", rpc, address, version);
//hash key = rpc + address + version
hashkey = crypto.createHash('sha256').update(rpc + address + version).digest('hex');
const params = {
TableName: TABLE_NAME,
Key: {
hashkey: hashkey,
},
};

try {
const response = await docClient.send(new GetCommand(params));
logger.info(response);
return response.Item;
} catch (error) {
logger.error(error);
return null;
}
}

app.post('/solana/GetAccountInfo', async (req, res) => {
const {rpc, address, version} = req.body;
if (!rpc || !address || !version) {
res.status(400).send({state: 400, error:'invalid request'});
return;
}

let resultdb = await get_from_db(rpc, address, version);
if(resultdb != null) {
let {status, data} = resultdb;
if(!status) {
status = 200;
}
res.status(status).type('application/json').send(data);
return;
}

var result = await get_solana_account(rpc, address);
if (result != null) {
let [status, data] = result;
await add_to_db(rpc, address, version, status, data);
res.status(status).type('application/json').send(data);
} else {
res.status(404).send({state: 404, error: 'not found', result: null});
}
});

app.post('/hssn/HypergridNode', async (req, res) => {
var {rpc, address, version} = req.body;
if(!rpc) {
rpc = HSSN_RPC_DEFAULT;
}
if (!rpc || !address || !version) {
res.status(400).send({state: 400, error:'invalid request'});
return;
}

let resultdb = await get_from_db(rpc, address, version);
if(resultdb != null) {
let {status, data} = resultdb;
if(!status) {
status = 200;
}
res.status(status).type('application/json').send(data);
return;
}

var result = await get_hypergrid_node(rpc, address);
if (result != null) {
let [status, data] = result;
await add_to_db(rpc, address, version, status, data);
res.status(status).type('application/json').send(data);
} else {
res.status(404).send({state: 404, error: 'not found', result: null});
}
});

app.listen(PORT, () => {
logger.info(`Server is running on port ${PORT}`);
});
4 changes: 1 addition & 3 deletions tools/solana.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@ import (

// global variables with default values
var SonicFeeProgramID = "SonicFeeSet1ement11111111111111111111111111"
var L1InboxProgramID = "5XJ1wZkTwAw9mc5FbM3eBgAT83TKgtAGzKos9wVxC6my"
var LocalPrivateKey = "~/.config/solana/id.json"
var SonicStateOracleURL = "https://oracle.sonic.game"
var SonicStateOracleURL = "https://nisaba-hssn.sonic.game"

// read variables from yaml file
func ReadVariablesFromYaml(filename string) {
Expand Down Expand Up @@ -57,7 +56,6 @@ func ReadVariablesFromYaml(filename string) {

// Set the global variables
SonicFeeProgramID = params["SonicFeeProgramID"].(string)
L1InboxProgramID = params["L1InboxProgramID"].(string)
LocalPrivateKey = params["LocalPrivateKey"].(string)
SonicStateOracleURL = params["SonicStateOracleURL"].(string)
}
Expand Down
12 changes: 4 additions & 8 deletions x/hypergridssn/keeper/msg_server_solana_account.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,8 @@ func (k msgServer) CreateSolanaAccount(goCtx context.Context, msg *types.MsgCrea
return nil, errorsmod.Wrap(sdkerrors.ErrKeyNotFound, "source not found")
}

// get account info from solana
resp, err := solana.GetAccountInfo(node.Rpc, msg.Address)
//TODO: get account info from oracle
//resp, err := solana.GetAccountFromOracle(node.Rpc, msg.Address, msg.Version)
//get account info from oracle
resp, err := solana.GetAccountFromOracle(node.Rpc, msg.Address, msg.Version)
if err != nil {
return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, err.Error())
}
Expand Down Expand Up @@ -87,10 +85,8 @@ func (k msgServer) UpdateSolanaAccount(goCtx context.Context, msg *types.MsgUpda
return nil, errorsmod.Wrap(sdkerrors.ErrKeyNotFound, "node not found")
}

// get account info from solana
resp, err := solana.GetAccountInfo(node.Rpc, msg.Address)
//TODO: get account info from oracle
// resp, err := solana.GetAccountFromOracle(node.Rpc, msg.Address, msg.Version)
//get account info from oracle
resp, err := solana.GetAccountFromOracle(node.Rpc, msg.Address, msg.Version)
if err != nil {
return nil, errorsmod.Wrap(sdkerrors.ErrUnauthorized, err.Error())
}
Expand Down

0 comments on commit 1ec4622

Please sign in to comment.