Universal Binary JSON
I'm on a vue.js v2 project. I need to parse a token after logged in. It is not a JWT token. It's a Ubjson token. I am using javascript, and I can't find any Ubjson token decoder anywhere.
If you know how to decode it, please help me out.
I've tried
https://www.npmjs.com/package/#shelacek/ubjson
import { Ubjson } from '#shelacek/ubjson'
const obj = Ubjson.decode(token)
console.log(obj) //undefined
Result
undefined
These solutions also work for me with fewer lines of code.
var ubjson = require("#shelacek/ubjson")
const token = '123***XYZ'
const buffer = Buffer.from(token, 'base64')
const obj = ubjson.decode(buffer)
console.log(obj)
There is a UBJSON encoder/decoder on NPM
See code-8's answer
Try something like this:
See in action [https://runkit.com/embed/3ngoupnl0unj]=
const ubjson = require('#shelacek/ubjson');
// https://stackoverflow.com/a/62364519/3330981
function base64ToBytesArr(str) {
const abc = [..."ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"]; // base64 alphabet
let result = [];
for(let i=0; i<str.length/4; i++) {
let chunk = [...str.slice(4*i,4*i+4)]
let bin = chunk.map(x=> abc.indexOf(x).toString(2).padStart(6,0)).join('');
let bytes = bin.match(/.{1,8}/g).map(x=> +('0b'+x));
result.push(...bytes.slice(0,3 - (str[4*i+2]=="=") - (str[4*i+3]=="=")));
}
return result;
}
const token = "e2kEdmVyc0kAAWkEdXNlcntpBG5hbWVTaRNiaGVuZ0B2aTNnbG9iYWwuY29taQRhcHBsU2kCVkNpBHNlcnZbJFUjaRC8L+g8i58TZQsAWbfrIuGgaQRwZXJtW3tpBG5hbWVTaQNFSURpBHBhcm1be2kEbmFtZVNpA0FQUGkEZGF0YVNpASp9XWkEZGF0YVNpSkJST08sQ05WRixDTlZaLERGUUwsREoxTCxGVjhaLEhZMEIsTjk0WCxSRDhMLFczWFYsWDNDWSxYUEg0LFlYNE4sWlIxMCxDT0xNfXtpBG5hbWVTaQNFSURpBHBhcm1be2kEbmFtZVNpA0FQUGkEZGF0YVNpAlZDfV1pBGRhdGFTaQlDT0xNLERGUUx9kEbmFtZVNpClZDX0dFVF9FSURpBHBhcm1be2kEbmFtZVNpBUJSQU5EaQRkYXRhU2kJQlJPTyxDT0xNfV1pBGRhdGFUfV19aQRyZWxtWyRVI2kQqBr68fUnmySYz31zLMgdOWkEYWxnb1NpClNIQTI1Ni1SU0FpBHNpZ25bJFUjSQCAokw8V8p06MkGqbm4Dry0ymUNQ2AM9TFd77vjFfJS3qHaGf/DYyYmkZamXUhOqFaucdVtkEgyQYMrDM2vOMILH7YnUVmgty8nH5Oim5w4aRQRepLcd14E98BnRjHovRS3KqeHoiON78gsTTcwhX1CE1hXlZxZGr6EJleEr8HbmMt9"
const obj = ubjson.decode(base64ToBytesArr(token));
console.log(obj);
Related
Im trying to use exactInput() function for UniV3 interface but when trying to execute the code the transactions fails https://goerli.etherscan.io/tx/0xb0d5e4b491610b9db8d98cc938008ba2a4e1a06e67b05ed87ac6c0ca3ad61dab
I know eth send shows 0 in this one but even especifying amount it fails, I dont know what to change..
I have checked many codes out there and cant see the mistake, please could someone give me some advice?
const {abi: V3SwapRouterABI} = require('#uniswap/v3-periphery/artifacts/contracts/interfaces/ISwapRouter.sol/ISwapRouter.json')
const { ethers } = require("ethers")
require("dotenv").config()
const INFURA_URL_TESTNET = process.env.INFURA_URL_TESTNET
const PRIVATE_KEY = process.env.PRIVATE_KEY
const WALLET_ADDRESS = process.env.WALLET_ADDRESS
// now you can call sendTransaction
const wethToken= "0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6"
const Uni= "0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984"
const UniswapRouter="0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45"
const UniV3Contract = new ethers.Contract(
UniswapRouter,
V3SwapRouterABI
)
const provider = new ethers.providers.JsonRpcProvider(INFURA_URL_TESTNET)
const wallet = new ethers.Wallet(PRIVATE_KEY)
const signer = wallet.connect(provider)
const FEE_SIZE = 3
function encodePath(path, fees) {
if (path.length != fees.length + 1) {
throw new Error('path/fee lengths do not match')
}
let encoded = '0x'
for (let i = 0; i < fees.length; i++) {
// 20 byte encoding of the address
encoded += path[i].slice(2)
// 3 byte encoding of the fee
encoded += fees[i].toString(16).padStart(2 * FEE_SIZE, '0')
}
// encode the final token
encoded += path[path.length - 1].slice(2)
return encoded.toLowerCase()
}
async function getToken() {
const path = encodePath([wethToken, Uni], [3000])
const deadline = Math.floor(Date.now()/1000) + (60*10)
const params = {
path: path,
recipient: WALLET_ADDRESS,
deadline: deadline,
amountIn: ethers.utils.parseEther('0.01'),
amountOutMinimum: 0
}
const encodedData = UniV3Contract.interface.encodeFunctionData("exactInput", [params])
const txArg = {
to: UniswapRouter,
from: WALLET_ADDRESS,
data: encodedData,
gasLimit: ethers.utils.hexlify(1000000)
}
const tx = await signer.sendTransaction(txArg)
console.log('tx: ', tx)
const receipt = tx.wait()
console.log('receipt: ', receipt)
}
module.exports = { getToken
You will need to remove the Deadline.. The new router 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45 moved deadline to the multi-call function (since the router is designed to be multi-call)
In my worker I am converting a base64 string I get from the request to a blob with some function. However, when I try to PUT the blob into my bucket, I get "Network Connection Lost" error. I can successfully PUT just the base64 string or any other string but not a blob. Here is my worker:
// Function to convert b64 to blob (working fine)
function b64toBlob(b64Data, contentType, sliceSize=512) {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
export default {
async fetch(request, env) {
const url = new URL(request.url);
const key = url.pathname.slice(1);
switch (request.method) {
case 'PUT':
const contentType = 'application/pdf';
const b64Data = request.body;
const blob = b64toBlob(b64Data, contentType);
try {
await env.qa_sub_agreements_bucket.put(key, blob, { // Failing here
httpMetadata: request.headers,
})
return new Response(blob) // Successfully returns the blob when above PUT is commented out
} catch (e) {
console.error(e.message, e.stack); // Logs out "Error: Network Connection Lost"
}
Hard to say definitively because the Worker posted doesn't appear to be totally complete. An eagle-eyed coworker spotted that it looks like the problem may be that you're invoking atob on a ReadableStream and likely that conversion is what's throwing the exception.
I'm trying to learn Axios and Vue with using Twitch API. I'm fetching data from that API and there is thumbnail_url which is for channel's thumbnail photos but I have to change that data's width and height because it's coming like this;
https://static-cdn.jtvnw.net/previews-ttv/live_user_shroud-{width}x{height}.jpg
And I was trying to do like this;
beforeMount(){
helix.get('streams?language=en').then((response) => {
for(var i=0; i < response.data.data.length; i++){
response.data.data[i].thumbnail_url.replace("width", "40")
}
console.log(response.data.data)
this.results = response.data.data
})
.catch(function (error) {
console.log(error);
});
},
Actually, I didn't understand what that is not working. I know there is a point that I missed. If someone can help me, It'd be great.
And If It is not correct way to do this, what is the correct way?
Thanks a lot.
You should use replace("{width}", "40"); instead
var url = 'https://static-cdn.jtvnw.net/previews-ttv/live_user_shroud-{width}x{height}.jpg';
url = url.replace("{width}", "40");
url = url.replace("{height}", "60");
console.log(url);
In your code change this
var thumbnail_url = response.data.data[i].thumbnail_url;
thumbnail_url = thumbnail_url.replace("{width}", "40");
thumbnail_url = thumbnail_url.replace("{height}", "60");
response.data.data[i].thumbnail_url = thumbnail_url;
As you comment you can do it without variable also
response.data.data[i].thumbnail_url = response.data.data[i].thumbnail_url.replace("{width}", "40").replace("{height}", "60");
I'm currently creating a library for an API. The endpoints have optional tags, and so I'm trying to create a way to use them in the functions.
import * as request from "request";
class Api {
key: string;
constructor(userInput: string) {
this.key = userInput;
}
champions(tags: object) {
Object.keys(tags).forEach(function(key) {
console.log(key + " = " + tags[key])
})
request(`https://api.champion.gg/v2/champions?api_key=${this.key}&${tags}`, function (error, response, body) {
if(!error && response.statusCode == 200) {
let info = JSON.parse(body)
}
});
}
}
var test = new Api("key")
test.champions({"champData": ["kda", "damage"], "rawr": ["xd", "lmao"]})
So far, the combining of Object.keys and forEach has allowed me to get the response of champData=kda,damage and rawr=xd,lmao, however, I need to be able to assign these to a variable that's usable in the URL. How can I get this to work?
Another issue that may occur later on is that, between each tag, there needs to be an & symbol, but not at the end. I apologize for throwing multiple problems into one, but because this is my first experience with something like this, I'm having many issues.
You can use Object.entries() and URLSearchParams()
const tags = {a:1, b:2, c:3};
const params = new URLSearchParams();
const key = "def";
Object.entries(tags).forEach(([key, prop]) => params.set(key, prop));
const url = `https://api.champion.gg/v2/champions?api_key=${key}&${params.toString()}`;
console.log(url);
I have an audio file/blob that has been created using the MediaRecorder api:
let recorder = new MediaRecorder(this.stream)
let data = [];
recorder.ondataavailable = event => data.push(event.data);
and then later when the recording is finished:
let superBlob = new Blob(data, { type: "video/webm" });
How can I use this blob to create an AudioBuffer? I need to either :
Transform the Blob object into an ArrayBuffer which I could use with AudioContext.decodeAudioData (returns an AudioBuffer) or
Transform the Blob object into an Float32Array, where I could copy it into the AudioBuffer with AudioBuffer.copyToChannel()
Any tips on how to achieve that are appreciated. Cheers!
To convert a Blob object to an ArrayBuffer, use FileReader.readAsArrayBuffer.
let fileReader = new FileReader();
let arrayBuffer;
fileReader.onloadend = () => {
arrayBuffer = fileReader.result;
}
fileReader.readAsArrayBuffer(superBlob);
The accepted answer is great but only gives an array buffer which is not an audio buffer. You need to use the audio context to convert the array buffer into an audio buffer.
const audioContext = AudioContext()
const fileReader = new FileReader()
// Set up file reader on loaded end event
fileReader.onloadend = () => {
const arrayBuffer = fileReader.result as ArrayBuffer
// Convert array buffer into audio buffer
audioContext.decodeAudioData(arrayBuffer, (audioBuffer) => {
// Do something with audioBuffer
console.log(audioBuffer)
})
}
//Load blob
fileReader.readAsArrayBuffer(blob)
I wish the answer had included an example using decodeAudioData. I had to find it somewhere else and I thought since this is the top search for "Blob to Audio Buffer" I would add some helpful information for the next person that comes down this rabbit hole.
All the answers are true. However, in the modern web browsers like Chrome 76 and Firefox 69, there is a much simpler way: using Blob.arrayBuffer()
Since Blob.arrayBuffer() returns a Promise, you can do either
superBlob.arrayBuffer().then(arrayBuffer => {
// Do something with arrayBuffer
});
or
async function doSomethingWithAudioBuffer(blob) {
var arrayBuffer = await blob.arrayBuffer();
// Do something with arrayBuffer;
}
A simplified version using an async function:
async function blobToAudioBuffer(audioContext, blob) {
const arrayBuffer = await blob.arrayBuffer();
return await audioContext.decodeAudioData(arrayBuffer);
}
I put audioContext as a param, because I recommend reusing instances.
Both Answers are true, there are some minor changes. This is the function I finally used:
function convertBlobToAudioBuffer(myBlob) {
const audioContext = new AudioContext();
const fileReader = new FileReader();
fileReader.onloadend = () => {
let myArrayBuffer = fileReader.result;
audioContext.decodeAudioData(myArrayBuffer, (audioBuffer) => {
// Do something with audioBuffer
});
};
//Load blob
fileReader.readAsArrayBuffer(myBlob);
}