Problems with deploying first smart contracts - solidity

Good day everyone!
I'm trying to deploy the first smart contracts according to the helloWorld manuals, but I'm getting an error please see the snippet. Tell me, please, what can be done about this? Tried lot of way to fix it but failed.
Thanks in advance!
import { Command } from ""commander"";
import prompts, { PromptObject } from ""prompts"";
import { isNumeric, Migration } from ""./utils"";
const program = new Command();
const migration = new Migration();
async function main() {
const promptsData: PromptObject[] = [];
program
.allowUnknownOption()
.option(""-kn, --key_number <key_number>"", ""Public key number"")
.option(
""-b, --balance <balance>"",
""Initial balance in EVERs (will send from Giver)"",
);
program.parse(process.argv);
const options = program.opts();
if (!options.key_number) {
promptsData.push({
type: ""text"",
name: ""keyNumber"",
message: ""Public key number"",
validate: value => (isNumeric(value) ? true : ""Invalid number""),
});
}
if (!options.balance) {
promptsData.push({
type: ""text"",
name: ""balance"",
message: ""Initial balance (will send from Giver)"",
validate: value => (isNumeric(value) ? true : ""Invalid number""),
});
}
const response = await prompts(promptsData);
const keyNumber = +(options.key_number || response.keyNumber);
const balance = +(options.balance || response.balance);
const signer = (await locklift.keystore.getSigner(keyNumber.toString()))!;
let accountsFactory = locklift.factory.getAccountsFactory(""Account"");
const { account: Account } = await accountsFactory.deployNewAccount({
publicKey: signer.publicKey,
initParams: {
_randomNonce: locklift.utils.getRandomNonce(),
},
constructorParams: {},
value: locklift.utils.toNano(balance),
});
migration.store(Account, ""account"");
console.log(`Account deployed at: ${Account.address}`);
}
main()
.then(() => process.exit(0))
.catch(e => {
console.log(e);
process.exit(1);
});"

Crashes on an attempt to collect Account contract assembly artefacts
There is no such thing in the build folder!

Related

Nuxt 3 - Server not ready on mount, Volar engine confused

I have two issues that may or may not be related.
Overview
Folder Structure
pages
|---user.vue
server
|---api
|---profile.get.ts
|---profile.post.ts
The tech is Nuxt3 using the server and Supabase.
profile.get.ts
import { serverSupabaseClient, serverSupabaseUser } from "#supabase/server"
import { Database } from "~~/types/supabase"
export default defineEventHandler(async (event) => {
try {
const supabase = serverSupabaseClient<Database>(event)
const user = await serverSupabaseUser(event)
const query = getQuery(event)
const { data, error } = await supabase.from('profiles').select('*').eq('email', query.email).single()
if (error) throw { status: error.code, message: error.message }
return { displayName: data.display_name, avatarUrl: data.avatar_url }
} catch (err) {
console.error('Handled Error:', err)
}
})
profile.post.ts
import { serverSupabaseClient } from "#supabase/server"
import { Database } from "~~/types/supabase"
export default defineEventHandler(async (event) => {
const supabase = serverSupabaseClient<Database>(event)
const { displayName, avatarUrl, email }: { displayName: string, avatarUrl: string, email: string } = await readBody(event)
const { error } = await supabase.from('profiles').update({ display_name: displayName, avatar_url: avatarUrl }).match({ email })
if (error) throw new Error(error.message)
return { status: 200 }
})
user.vue Snippet
onMounted(() => {
setTimeout(() => {
getProfile()
}, 100) // Fails when around 50 or less
})
async function getProfile() {
const { data, error } = await useFetch('/api/profile', { method: 'GET', params: { email: user.value?.email } })
console.log(data.value)
console.log(error.value)
displayName.value = data.value!.displayName || ''
avatarUrl.value = data.value!.avatarUrl || ''
}
Problem 1
When user.vue mounts, I want to call my Nuxt API (profile.get.ts) and fetch user data (display name, avatar url) from the Supabase database. However, I receive this error when fetching on mount: FetchError: 404 Cannot find any route matching /api/profile. (/api/profile). However, if I use setTimeout to 100ms, it fetches fine. That makes me think the API server is simply not ready, but the documentation doesn't mention that and encourages fetching during lifecycle.
Problem 2
Volar seems to be confused about the typing of data from getProfile().
Property 'displayName' does not exist on type '{ status: number; } | { displayName: string | null; avatarUrl: string | null; }'.
Property 'displayName' does not exist on type '{ status: number; }'.ts(2339)
However, this is the typing from profile.post.ts even though I'm using profile.get.ts.
Current Behavior
Without setTimeout at 100ms or greater, it will fail with the 404 message
With setTimeout at 100ms or greater, or with getProfile() called from a button, there is no issue, even with the TypeScript errors, etc.
Desired Behavior
TypeScript correctly recognizes the proper endpoint (profiles.get.ts since I'm calling it with get)
Data can be fetched on mount from the API without the use of setTimeout

Nestjs - file upload with fastify multipart

I am trying to upload multiple files with nestjs using the fastify adapter. I can do so following the tutorial in this link -article on upload
Now this does the job of file upload using fastify-multipart, but I couldnt make use of the request validations before uploading,
for example, here is my rule-file-models (which later I wanted to save to postgre)
import {IsUUID, Length, IsEnum, IsString, Matches, IsOptional} from "class-validator";
import { FileExtEnum } from "./enums/file-ext.enum";
import { Updatable } from "./updatable.model";
import {Expose, Type} from "class-transformer";
export class RuleFile {
#Expose()
#IsUUID("4", { always: true })
id: string;
#Expose()
#Length(2, 50, {
always: true,
each: true,
context: {
errorCode: "REQ-000",
message: `Filename shouldbe within 2 and can reach a max of 50 characters`,
},
})
fileNames: string[];
#Expose()
#IsEnum(FileExtEnum, { always: true, each: true })
fileExts: string[];
#IsOptional({each: true, message: 'File is corrupated'})
#Type(() => Buffer)
file: Buffer;
}
export class RuleFileDetail extends RuleFile implements Updatable {
#IsString()
#Matches(/[aA]{1}[\w]{6}/)
recUpdUser: string;
}
And I wanted to validate the multipart request and see if these are set properly.
I cannot make it to work with event subscription based approach. Here are a few things I tried - adding the interceptor, to check for the request
#Injectable()
export class FileUploadValidationInterceptor implements NestInterceptor {
intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
const req: FastifyRequest = context.switchToHttp().getRequest();
console.log('inside interceptor', req.body);
// content type cmes with multipart/form-data;boundary----. we dont need to valdidate the boundary
// TODO: handle split errors based on semicolon
const contentType = req.headers['content-type'].split(APP_CONSTANTS.CHAR.SEMI_COLON)[0];
console.log(APP_CONSTANTS.REGEX.MULTIPART_CONTENT_TYPE.test(contentType));
const isHeaderMultipart = contentType != null?
this.headerValidation(contentType): this.throwError(contentType);
**// CANNOT check fir req.file() inside this, as it throws undefined**
return next.handle();
}
headerValidation(contentType) {
return APP_CONSTANTS.REGEX.MULTIPART_CONTENT_TYPE.test(contentType) ? true : this.throwError(contentType);
}
throwError(contentType: string) {
throw AppConfigService.getCustomError('FID-HEADERS', `Request header does not contain multipart type:
Provided incorrect type - ${contentType}`);
}
}
I wasnt able to check req.file() in the above interceptor. It throws as undefined. I tried to follow the fastify-multipart
But I wasnt able to get the request data in a prehandler as provided in the documentation for fastify-multipart
fastify.post('/', async function (req, reply) {
// process a single file
// also, consider that if you allow to upload multiple files
// you must consume all files othwise the promise will never fulfill
const data = await req.file()
data.file // stream
data.fields // other parsed parts
data.fieldname
data.filename
data.encoding
data.mimetype
// to accumulate the file in memory! Be careful!
//
// await data.toBuffer() // Buffer
//
// or
await pump(data.file, fs.createWriteStream(data.filename))
I tried getting via by registering a prehandler hook of my own like this (executed as iife)
(async function bootstrap() {
const appConfig = AppConfigService.getAppCommonConfig();
const fastifyInstance = SERVERADAPTERINSTANCE.configureFastifyServer();
// #ts-ignore
const fastifyAdapter = new FastifyAdapter(fastifyInstance);
app = await NestFactory.create<NestFastifyApplication>(
AppModule,
fastifyAdapter
).catch((err) => {
console.log("err in creating adapter", err);
process.exit(1);
});
.....
app.useGlobalPipes(
new ValidationPipe({
errorHttpStatusCode: 500,
transform: true,
validationError: {
target: true,
value: true,
},
exceptionFactory: (errors: ValidationError[]) => {
// send it to the global exception filter\
AppConfigService.validationExceptionFactory(errors);
},
}),
);
app.register(require('fastify-multipart'), {
limits: {
fieldNameSize: 100, // Max field name size in bytes
fieldSize: 1000000, // Max field value size in bytes
fields: 10, // Max number of non-file fields
fileSize: 100000000000, // For multipart forms, the max file size
files: 3, // Max number of file fields
headerPairs: 2000, // Max number of header key=>value pairs
},
});
(app.getHttpAdapter().getInstance() as FastifyInstance).addHook('onRoute', (routeOptions) => {
console.log('all urls:', routeOptions.url);
if(routeOptions.url.includes('upload')) {
// The registration actually works, but I cant use the req.file() in the prehandler
console.log('###########################');
app.getHttpAdapter().getInstance().addHook('preHandler', FilePrehandlerService.fileHandler);
}
});
SERVERADAPTERINSTANCE.configureSecurity(app);
//Connect to database
await SERVERADAPTERINSTANCE.configureDbConn(app);
app.useStaticAssets({
root: join(__dirname, "..", "public"),
prefix: "/public/",
});
app.setViewEngine({
engine: {
handlebars: require("handlebars"),
},
templates: join(__dirname, "..", "views"),
});
await app.listen(appConfig.port, appConfig.host, () => {
console.log(`Server listening on port - ${appConfig.port}`);
});
})();
Here is the prehandler,
export class FilePrehandlerService {
constructor() {}
static fileHandler = async (req, reply) => {
console.log('coming inside prehandler');
console.log('req is a multipart req',await req.file);
const data = await req.file();
console.log('data received -filename:', data.filename);
console.log('data received- fieldname:', data.fieldname);
console.log('data received- fields:', data.fields);
return;
};
}
This pattern of registring and gettin the file using preHandler works in bare fastify application. I tried it
Bare fastify server:
export class FileController {
constructor() {}
async testHandler(req: FastifyRequest, reply: FastifyReply) {
reply.send('test reading dne');
}
async fileReadHandler(req, reply: FastifyReply) {
const data = await req.file();
console.log('field val:', data.fields);
console.log('field filename:', data.filename);
console.log('field fieldname:', data.fieldname);
reply.send('done');
}
}
export const FILE_CONTROLLER_INSTANCE = new FileController();
This is my route file
const testRoute: RouteOptions<Server, IncomingMessage, ServerResponse, RouteGenericInterface, unknown> = {
method: 'GET',
url: '/test',
handler: TESTCONTROLLER_INSTANCE.testMethodRouteHandler,
};
const fileRoute: RouteOptions = {
method: 'GET',
url: '/fileTest',
preHandler: fileInterceptor,
handler: FILE_CONTROLLER_INSTANCE.testHandler,
};
const fileUploadRoute: RouteOptions = {
method: 'POST',
url: '/fileUpload',
preHandler: fileInterceptor,
handler: FILE_CONTROLLER_INSTANCE.fileReadHandler,
};
const apiRoutes = [testRoute, fileRoute, fileUploadRoute];
export default apiRoutes;
Could someone let me know the right the way to get the fieldnames , validate them befr the service being called in Nestjs
Well, I have done something like this and It works great for me. Maybe it can work for you too.
// main.ts
import multipart from "fastify-multipart";
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
);
app.register(multipart);
// upload.guard.ts
import {
Injectable,
CanActivate,
ExecutionContext,
BadRequestException,
} from "#nestjs/common";
import { FastifyRequest } from "fastify";
#Injectable()
export class UploadGuard implements CanActivate {
public async canActivate(ctx: ExecutionContext): Promise<boolean> {
const req = ctx.switchToHttp().getRequest() as FastifyRequest;
const isMultipart = req.isMultipart();
if (!isMultipart)
throw new BadRequestException("multipart/form-data expected.");
const file = await req.file();
if (!file) throw new BadRequestException("file expected");
req.incomingFile = file;
return true;
}
}
// file.decorator.ts
import { createParamDecorator, ExecutionContext } from "#nestjs/common";
import { FastifyRequest } from "fastify";
export const File = createParamDecorator(
(_data: unknown, ctx: ExecutionContext) => {
const req = ctx.switchToHttp().getRequest() as FastifyRequest;
const file = req.incomingFile;
return file
},
);
// post controller
#Post("upload")
#UseGuards(UploadGuard)
uploadFile(#File() file: Storage.MultipartFile) {
console.log(file); // logs MultipartFile from "fastify-multipart"
return "File uploaded"
}
and finally my typing file
declare global {
namespace Storage {
interface MultipartFile {
toBuffer: () => Promise<Buffer>;
file: NodeJS.ReadableStream;
filepath: string;
fieldname: string;
filename: string;
encoding: string;
mimetype: string;
fields: import("fastify-multipart").MultipartFields;
}
}
}
declare module "fastify" {
interface FastifyRequest {
incomingFile: Storage.MultipartFile;
}
}
So I found a simpler alternative. I started using fastify-multer. I used it along with this awesome lib - which made me use the multer for fastify - #webundsoehne/nest-fastify-file-upload
These are the changes I made. I registered the multer content process.
app.register(multer( {dest:path.join(process.cwd()+'/upload'),
limits:{
fields: 5, //Number of non-file fields allowed
files: 1,
fileSize: 2097152,// 2 MB,
}}).contentParser);
Then in the controller - I use it as the nestjs doc says . This actually makes fasitfy work with multer
#UseInterceptors(FileUploadValidationInterceptor, FileInterceptor('file'))
#Post('/multerSample')
async multerUploadFiles(#UploadedFile() file, #Body() ruleFileCreate: RuleFileCreate) {
console.log('data sent', ruleFileCreate);
console.log(file);
// getting the original name of the file - no matter what
ruleFileCreate.originalName = file.originalname;
return await this.fileService.fileUpload(file.buffer, ruleFileCreate);
}
BONUS - storing the file in local and storing it in DB - Please refer
github link

NestJs - Jest - Testing: ConnectionNotFoundError: Connection "default" was not found

I am trying to write a test of a simple TODO App.
This is my service test class:
const mockTaskRepository = () => ({
createTask: jest.fn(),
});
describe('TasksService', () => {
let tasksService;
let taskRepository;
beforeEach(async () => {
const module = await Test.createTestingModule({
providers: [TasksService, { provide: TaskRepository, useFactory: mockTaskRepository }],
}).compile();
tasksService = await module.get<TasksService>(TasksService);
taskRepository = await module.get<TaskRepository>(TaskRepository);
});
describe('create task', () => {
it('calls taskRepository.create() and returns the result', async () => {
const createTaskDto = {
title: 'Test task',
description: 'Test desc',
};
taskRepository.createTask.mockResolvedValue('someTask');
expect(taskRepository.createTask).not.toHaveBeenCalled();
const result = await tasksService.createTask(createTaskDto);
expect(taskRepository.createTask).toHaveBeenCalledWith(createTaskDto);
expect(result).toEqual('someValue');
});
});
});
And this is my task service:
#Injectable()
export class TasksService {
constructor(
#InjectRepository(TaskRepository)
private taskRepository: TaskRepository,
) {}
async createTask(createTaskDto: CreateTaskDto): Promise<Task> {
const { title, description } = createTaskDto;
const task = new Task();
task.title = title;
task.description = description;
task.status = TaskStatus.IN_PROGRESS;
await task.save();
return task;
}
}
When I try to run the Create a Task test, the error below occurs.
FAIL src/tasks/tasks.service.spec.ts
● TasksService › create task › calls taskRepository.create() and returns the result
ConnectionNotFoundError: Connection "default" was not found.
at new ConnectionNotFoundError (error/ConnectionNotFoundError.ts:8:9)
at ConnectionManager.Object.<anonymous>.ConnectionManager.get (connection/ConnectionManager.ts:40:19)
at Object.getConnection (index.ts:247:35)
at Function.Object.<anonymous>.BaseEntity.getRepository (repository/BaseEntity.ts:85:72)
at Task.Object.<anonymous>.BaseEntity.save (repository/BaseEntity.ts:50:42)
at TasksService.createTask (tasks/tasks.service.ts:35:14)
at Object.<anonymous> (tasks/tasks.service.spec.ts:69:38)
Test Suites: 1 failed, 1 passed, 2 total
Tests: 1 failed, 8 passed, 9 total
Anyone know what's the mistake in the code?
..........................................
Thanks in advance!
If it is looking for connection default then I assume that the TypeOrmModule configs are still being taken into account. Instead of provide: TaskRepository try changing it to provide: getRepositoryToken(TaskEntity) if you have a TaskEntity. This will tell Nest to override the default repo that the #InjectRepository() decorator tries to provide.
If that isn't the case, do you think you could add your TaskService and TaskModule classes as well?
You should mock the repository then bringing up the context of Test Module. Otherwise, the real Repository is being injected (via Nest's DI) into service.
const module = await Test.createTestingModule({
providers: [
{
provide: getRepositoryToken(YourEntityClass),
useValue: mockedRepo, // or use class
},
TasksService],
}).compile();
tasksService = await module.get<TasksService>(TasksService);
// taskRepository = await module.get<TaskRepository>(TaskRepository); don't have to do that if `useValue` was used instead of factory
So, TL;DR :
provide: TaskRepository should provide Token of given Injectable in this case: https://docs.nestjs.com/fundamentals/custom-providers#non-class-based-provider-tokens
The test expected method Repository.createTask to be called, but method Service.createTask didn't make that call.
The fix: Update the Service method to delegate to the Repository method the task creation.
// tasks.service.ts
async createTask(createTaskDto: CreateTaskDto, user: User): Promise<Task> {
return this.taskRepository.createTask(createTaskDto, user);
}
// tasks.repository.ts
async createTask(createTaskDto: CreateTaskDto, user: User): Promise<Task> {
const { title, description } = createTaskDto;
const task = new Task();
task.title = title;
task.user = user;
task.description = description;
task.status = TaskStatus.IN_PROGRESS;
await task.save();
delete task.user;
return task;
}
}

relay subscription onNext not triggered on react-native

I am a subscription setup but onNext is not getting triggered I am not sure why since this is my first time implementing subscription and docs was not much help with the issue.
Here are the code implementations:
import {
graphql,
requestSubscription
} from 'react-relay'
import environment from '../network';
const subscription = graphql`
subscription chatCreatedSubscription{
chatCreated{
id
initiate_time
update_time
support_id
category_id
email
name
}
}
`;
function chatCreated(callback) {
const variables = {};
requestSubscription(environment, {
subscription,
variables,
onNext: () => {
console.log("onNext");
callback()
},
updater: () => {
console.log("updater");
}
});
}
module.exports = chatCreated;
and here is my network for the subscription
import { Environment, Network, RecordSource, Store } from "relay-runtime";
import Expo from "expo";
import { SubscriptionClient } from "subscriptions-transport-ws";
import { WebSocketLink } from 'apollo-link-ws';
import { execute } from 'apollo-link';
import accessHelper from "../helper/accessToken";
const networkSubscriptions = async (operation, variables) => {
let token = await accessHelper();
if (token != null || token != undefined) {
const subscriptionClient = new SubscriptionClient("ws://localhost:3000/graphql",
{
reconnect: true,
connectionParams: {
Authorization: token,
},
});
execute(new WebSocketLink(subscriptionClient), {
query: operation.text,
variables,
});
}
}
const network = Network.create(fetchQuery, networkSubscriptions);
const store = new Store(new RecordSource());
const environment = new Environment({
network,
store
});
export default environment;
the subscription is called in a componentDidMount method on a component it executes but the onNext method inside the subscription is never triggered when new information is added to what the subscription is listening to.
so i figured out that my issue was the network js not being setup properly and the version of subscription-transport-ws. i added version 0.8.3 of the package and made the following changes to my network file:
const networkSubscriptions = async (config, variables, cacheConfig, observer) => {
const query = config.text;
let token = await accessHelper();
if (token != null || token != undefined) {
const subscriptionClient = new SubscriptionClient(`ws://${api}/graphql`,
{
reconnect: true,
connectionParams: {
Authorization: token,
},
});
subscriptionClient.subscribe({ query, variables }, (error, result) => {
observer.onNext({ data: result })
})
return {
dispose: subscriptionClient.unsubscribe
};
}
}
i hope this helps you if you get stuck with the same issue as mine.

Relay subscriptions not working with react-native

I'm using Express Graphql server with react native and Relay. My device does connects to the subscription but it does not subscribe to it. Here's my index.js on the server
const subscriptionServer = SubscriptionServer.create(
{
execute,
subscribe,
schema,
onOperation: (message, params, webSocket) => {
console.log(params)
return params;
},
onConnect: () => {
// My device does connects
console.log("client connected")
}
},
{
server,
path: '/subscriptions'
},
);
app.use('/graphql', graphqlHTTP({
schema,
graphiql: true
}));
app.use('/graphiql', graphiqlExpress({
endpointURL: '/graphql',
subscriptionsEndpoint: `ws://127.0.0.1:8080/subscriptions`
}));
server.listen(PORT, ()=> {
console.log("Groceries running on port " + PORT)
console.log(
`subscriptions is now running on ws://localhost:${PORT}/subscriptions'}`
);
});
The resolver for subscription on the server, it was quite troublesome to figure out since everyone is using executable schema from apolloGraphql.
export default {
type: OrderEdges,
args: {
ShopId: {type: GraphQLID},
},
subscribe: withFilter(() => pubsub.asyncIterator('orderConfirmed'), (payload, variables) => {
console.log(payload)
console.log(variables)
return payload.orderConfirmed.node.ShopId == variables.ShopId;
}),
}
Now the react-native client. My subscription setup with relay environment.
const setupSubscriptions = (config, variables, cacheConfig, observer) => {
const query = config.text; //does console logs the query
const subscriptionClient = new SubscriptionClient(`ws://192.168.0.100:8080/subscriptions`, {reconnect:true});
subscriptionClient.request({query, variables}, (err, result) => {
console.log(err) // doesn't get call inside the request method
observer.onNext(data:result)
})
}
My subscription method,
export default function() {
const variables = {
ShopId: shop.getShop()[0].id
}
requestSubscription(
environment,
{
subscription,
variables,
onCompleted: (res, err) => {
console.log(res)
console.log(err)
},
updater: (store) => {...},
onError: error => console.error(error),
onNext: (response) => {console.log(response)}
});
}
the component where I'm calling to subscribe,
import subscription from '../../GraphQLQueries/subscriptions/orderConfirmed';
class OrdersBox extends React.Component {
constructor(props) {
super(props);
}
componentDidMount() {
//initializing subscription
orderSubscriptions();
}
When the device starts the app, my device is connected to the web socket as I can see the console.log statement inside the onConnect method in SubscriptionServer. But when the payload is published after a mutation, the subscribe method doesn't get called. I can't seem to figure out what I'm doing wrong. Maybe it's some react-native specific config that I'm missing cuz everything seems to work fine when I test it on graphiql.
I can't find any example of react-native and relay subscriptions used with express graphql.
note: Everything is working when I use subscription with graphiql. But not with react-native and relay.
Thanks in advance guys
....
I wasn't returning the subscriptionClient.request method. Adding a return statement solved the problem. You don't have to return when using subscribe method in subscriptions-transport-ws#0.8.3. But version 0.9.1 replaces the subscribe function with request which does require it to return.
try:
function setupSubscription(config, variables, cacheConfig, observer) {
const query = config.text;
const subscriptionClient = new SubscriptionClient(websocketURL, {
reconnect: true
});
const client = subscriptionClient.request({ query, variables }).subscribe({
next: result => {
observer.onNext({ data: result.data });
},
complete: () => {
observer.onCompleted();
},
error: error => {
observer.onError(error);
}
});
return {
dispose: client.unsubscribe
};
}
subscriptions-transport-ws#0.9.1